INITIALIZATION Knowledgebase: ki-dev-large Base Query: tell me more about the git version control Model: gemini-1.5-pro-preview-0409 Use Curl?: None ================================================== **Elapsed Time: 0.00 seconds** ================================================== ROUTING Query type: summary ================================================== **Elapsed Time: 2.17 seconds** ================================================== RAG PARAMETERS Max Context To Include: 100 Lowest Score to Consider: 0.1 ================================================== **Elapsed Time: 0.14 seconds** ================================================== VECTOR SEARCH ALGORITHM TO USE Use MMR search?: True Use Similarity search?: False ================================================== **Elapsed Time: 0.10 seconds** ================================================== VECTOR SEARCH DONE ================================================== **Elapsed Time: 6.13 seconds** ================================================== PRIMER Primer: You are Simon, a highly intelligent personal assistant in a system called KIOS. You are a chatbot that can read knowledgebases through the "CONTEXT" that is included in the user's chat message. Your role is to act as an expert at summarization and analysis. In your responses to enterprise users, prioritize clarity, trustworthiness, and appropriate formality. Be honest by admitting when a topic falls outside your scope of knowledge, and suggest alternative avenues for obtaining information when necessary. Make effective use of chat history to avoid redundancy and enhance response relevance, continuously adapting to integrate all necessary details in your interactions. Use as much tokens as possible to provide a detailed response. ================================================== **Elapsed Time: 0.18 seconds** ================================================== FINAL QUERY Final Query: CONTEXT: ########## File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 1 Context: # Git Magic **Ben Lynn** August 2007 ## Preface Git is a version control Swiss army knife. A reliable versatile multipurpose revision control tool whose extraordinary flexibility makes it tricky to learn, let alone master. As Arthur C. Clarke observed, any sufficiently advanced technology is indistinguishable from magic. This is a great way to approach Git: newbies can ignore its inner workings and view Git as a gizmo that can amaze friends and infuriate enemies with its wondrous abilities. Rather than go into details, we provide rough instructions for particular effects. After repeated use, gradually you will understand how each trick works, and how to tailor the recipes for your needs. - **Simplified Chinese:** by JunJie, Meng and JiangWei. Converted to Traditional Chinese via iconv -f UTF-8 -t UTF-8-TW. - **French:** by Alexandre Garel, Paul Gaborit, and Nicolas Deram. - **German:** by Benjamin Bellee and Armin Stebich; also hosted on Armin's website. - **Italian:** by Mattia Rigotti. - **Korean:** by Jung-Ho (John) Han; also hosted on John's website. - **Polish:** by Damian Michna. - **Brazilian Portuguese:** by José Inácio Serafini and Leonardo Siqueira Rodrigues. - **Russian:** by Tikhon Taravasky, Mikhail Dymkov, and others. - **Spanish:** by Rodrigo Toledo and Ariset Llerena Tapia. - **Ukrainian:** by Volodymyr Bodevchik. - **Vietnamese:** by Trần Ngọc Quân; also hosted on his website. - Single webpage: barebones HTML, with no CSS. #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 2 Context: # Documentation - **PDF file**: printer-friendly. - **EPUB file**: E-reader-friendly. - **Debian package**: Ubuntu package; get a fast and local copy of this site. Handy when this server is offline. - **Physical book**: [Amazon](https://www.amazon.com): 64 pages, 15.24cm x 22.86cm, black and white. Handy when there is no electricity. ## Thanks! I'm humbled that so many people have worked on translations of these pages. I greatly appreciate having a wider audience because of the efforts of those named above. - Dustin Sallings - Alberto Bertogli - James Cameron - Douglas Livingston - Michael Budde - Richard Albury - Tarmigan - Derek Mahar - Frode Aanevik - Keith Patrick - Andy Somerville - Ralf Recker - Øyvind A. Holm - Miklos Vajna - Sébastien Hinderer - Thomas Miedl - Joe Malin - Tyler Breese - Sonia Hamilton - Julian Haagsman - Roman Lesniak - Sergey Litvinov - Oliver Ferrigni - David Toca - Jodi Thiefry - Baiju Muthukadan contributed corrections and improvements. François Marier maintains the Debian package originally created by Daniel Baumann. My gratitude goes to many others for your support and praise. I'm tempted to quote you here, but it might raise expectations to ridiculous heights. If I've left you out by mistake, please tell me or just send me a patch! ## License This guide is released under the GNU General Public License, version 3 or any later version published by the Free Software Foundation. Naturally, the source is kept in a Git repository and can be obtained by typing: ``` $ git clone git://repo.or.cz/gitmisc.git # Creates "gitmisc" directory. ``` or from one of the mirrors: ``` $ git clone git://github.com/blyn/gitmagic.git $ git clone git://git.asembla.com/gitmagic.git $ git clone git@bitbucket.org:blyn/gitmagic.git ``` GitHub, Asembla, and Bitbucket support private repositories; the latter two for free. #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 3 Context: # Introduction I'll use an analogy to introduce version control. See the [Wikipedia entry](https://en.wikipedia.org/wiki/Version_control) on revision control for a saner explanation. ## Work is Play I've played computer games almost all my life. In contrast, I only started using version control systems as an adult. I suspect I'm not alone, and comparing the two may make these concepts easier to explain and understand. Think of editing your code, or document, as playing a game. Once you’ve made a lot of progress, you’d like to save. To do so, you click on the **Save** button in your text editor. But this will overwrite the old version. It’s like those old school games which only had one save slot: sure you could save, but you could never go back to an older state. Which was a shame, because your previous save might have been right at an exceptionally fun part of the game that you’d like to revisit one day. Or worse still, your current save is in an unwinable state, and you have to start again. ## Version Control When editing, you can **Save As...** a different file, or copy the file somewhere first before saving if you want to savor old versions. You can compress them too to save space. This is a primitive and labour-intensive form of version control. Computer games improved on this long ago, many of them providing multiple automatically timestamped save slots. Let’s make the problem slightly tougher. Say you have a bunch of files that go together, such as source code for a project, or files for a website. Now if you want to keep an old version you have to archive a whole directory. Keeping many versions around by hand is inconvenient, and quickly becomes expensive. With some computer games, a saved game really does consist of a directory full of files. These games hide this detail from the player and present a convenient interface to manage different versions of this directory. Version control systems are no different. They all have nice interfaces to manage a directory of stuff. You can save the state of the directory every so often, and you can load any one of the saved states later on. Unlike most computer games, they’re usually smart about conserving space. Typically, only a few files change from version to version, and not much. Storing the differences instead of entire new copies saves room. #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 4 Context: # Distributed Control Now imagine a very difficult computer game. So difficult to finish that many experienced gamers all over the world decide to team up and share their saved games to try to beat it. Speedruns are real-life examples: players specializing in different levels of the same game collaborate to produce amazing results. How would you set up a system so they can get at each other’s saves easily? And upload new ones? In the old days, every project used centralized version control. A server somewhere held all the saved games. Nobody else did. Every player kept at most a few saved games on their machine. When a player wanted to make progress, they’d download the latest save from the main server, play a while, save and upload back to the server for everyone else to use. What if a player wanted to get an older saved game for some reason? Maybe the current saved game is in an unwinnable state because somebody forgot to pick up an object back in level three, and they want to find the latest saved game where the game can still be completed. Or maybe they want to compare two older saved games to see how much work a particular player did. There could be many reasons to want to see an older revision, but the outcome is the same. They have to ask the central server for that old saved game. The more saved games they want, the more they need to communicate. The new generation of version control systems, of which Git is a member, are known as distributed systems, and can be thought of as a generalization of centralized systems. When players download from the main server, they get every saved game, not just the latest one. It’s as if they’re mirroring the central server. This initial cloning operation can be expensive, especially if there’s a long history, but it pays off in the long run. One immediate benefit is that when an old save is desired for any reason, communication with the central server is unnecessary. ## A Silly Superstition A popular misconception is that distributed systems are ill-suited for projects requiring an official central repository. Nothing could be further from the truth. Photographing someone does not cause their soul to be stolen. Similarly, cloning the master repository does not diminish its importance. A good first approximation is that anything a centralized version control system can do, a well-designed distributed system can do better. Network resources are simply costlier than local resources. While we shall later see there are drawbacks to a distributed approach, one is less likely to make erroneous comparisons with this rule of thumb. A small project may only need a fraction of the features offered by such a system. #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 5 Context: # Git Basics ## Merge Conflicts For this topic, our computer game analogy becomes too thinly stretched. Instead, let us again consider editing a document. Suppose Alice inserts a line at the beginning of a file, and Bob appends one at the end of his copy. They both upload their changes. Most systems will automatically deduce a reasonable course of action: accept and merge their changes, so both Alice's and Bob's edits are applied. Now suppose both Alice and Bob have made distinct edits to the same line. Then it is impossible to proceed without human intervention. The second person to upload is informed of a **merge conflict**, and must choose one edit over another, or revise the line entirely. More complex situations can arise. Version control systems handle the simpler cases themselves, and leave the difficult cases for humans. Usually their behavior is configurable. ## Basic Tricks Rather than diving into a sea of Git commands, use these elementary examples to get your feet wet. Despite their simplicity, each of them are useful. Indeed, in my first months with Git I never ventured beyond the material in this chapter. ### Saving State About to attempt something drastic? Before you do, take a snapshot of all files in the current directory with: ```bash $ git init $ git add . $ git commit -m "My first backup" ``` Now if your new edits go awry, restore the pristine version: ```bash $ git reset --hard ``` To save the state again: ```bash $ git commit -a -m "Another backup" ``` #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 6 Context: # Add, Delete, Rename The above only keeps track of the files that were present when you first ran `git add`. If you add new files or subdirectories, you'll have to tell Git: ```bash $ git add readme.txt Documentation ``` Similarly, if you want Git to forget about certain files: ```bash $ git rm kludge.h obsolete.c $ git rm -r incriminating/evidence/ ``` `git` deletes these files for you if you haven't already. Renaming a file is the same as removing the old name and adding the new name. There's also the shortcut `git mv` which has the same syntax as the `mv` command. For example: ```bash $ git mv bug.c feature.c ``` # Advanced Undo/Redo Sometimes you just want to go back and forget about every change past a certain point because they’re all wrong. Then: ```bash $ git log ``` shows you a list of recent commits, and their SHA1 hashes: ``` commit 766f98189604240ba334153047649b88b8f11c664 Author: Bob Date: Tue Mar 14 01:59:26 2000 -0800 Replace printf() with write(). commit 82f5ea3462e651544956a8653c05f58d151275c Author: Alice Date: Thu Jan 1 00:00:00 1970 +0000 Initial commit. ``` The first few characters of the hash are enough to specify the commit; alternatively, copy and paste the entire hash. Type: ```bash $ git reset --hard 766f ``` to restore the state to a given commit and erase all newer commits from the record permanently. Other times you want to hop to an old state briefly. In this case, type: ```bash $ git checkout 8215 ``` #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 7 Context: This takes you back in time, while preserving server commits. However, like time travel in a science-fiction movie, if you now edit and commit, you will be in an alternate reality, because your actions are different to what they were the first time around. This alternate reality is called a **branch**, and we’ll have more to say about this later. For now, just remember that: ```bash $ git checkout master ``` will take you back to the present. Also, to stop Git complaining, always commit or reset your changes before running checkout. To take the computer game analogy again: - `git reset --hard`: load an old save and delete all saved games newer than the one just loaded. - `git checkout`: load an old game, but if you play on, the game state will deviate from the newer saves you made the first time around. Any saved games you make now will end up in a separate branch representing the alternate reality you have entered. We deal with this later. You can choose only to restore particular files and subdirectories by appending them after the command: ```bash $ git checkout some.file another.file ``` Take care, as this form of `checkout` can silently overwrite files. To prevent accidents, commit before running any checkout command, especially when first learning Git. In general, whenever you feel unsure about any operation, Git command or not, first run: ```bash $ git commit -a ``` Don’t like cutting and pasting hashes? Then use: ```bash $ git checkout :/"My first b" ``` to jump to the commit that starts with a given message. You can also ask for the 5th-last saved state: ```bash $ git checkout master~5 ``` ## Reverting In a court of law, events can be stricken from the record. Likewise, you can pick specific commits to undo. ```bash $ git commit -a $ git revert ``` will undo just the commit with the given hash. The revert is recorded as a new commit, which you can confirm by running: ```bash $ git log ``` #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 8 Context: # Changelog Generation Some projects require a changelog. Generate one by typing: ```bash $ git log > ChangeLog ``` ## Downloading Files Get a copy of a project managed with Git by typing: ```bash $ git clone git://server/path/to/files ``` For example, to get all the files I used to create this site: ```bash $ git clone git://git.or.cz/gitmagic.git ``` We'll have much to say about the clone command soon. ## The Bleeding Edge If you've already downloaded a copy of a project using `git clone`, you can upgrade to the latest version with: ```bash $ git pull ``` ## Instant Publishing Suppose you've written a script you'd like to share with others. You could just tell them to download from your computer, but if they do so while you're improving the script or making experimental changes, they could wind up in trouble. Of course, this is why release cycles exist. Developers may work on a project frequently, but they only make the code available when they feel it is presentable. To do this with Git, in the directory where your script resides: ```bash $ git init $ git add . $ git commit -m "First release" ``` Then tell your users to run: ```bash $ git clone your.computer:/path/to/script ``` to download your script. This assumes they have SSH access. If not, run `git daemon` and tell your users to instead run: ```bash $ git clone git://your.computer/path/to/script ``` From now on, every time your script is ready for release, execute: ```bash $ git commit -a -m "Next release" ``` #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 9 Context: and your users can upgrade their version by changing to the directory containing your script and typing: ```bash $ git pull ``` Your users will never end up with a version of your script you don’t want them to see. ## What Have I Done? Find out what changes you’ve made since the last commit with: ```bash $ git diff ``` Or since yesterday: ```bash $ git diff "@{yesterday}" ``` Or between a particular version and 2 versions ago: ```bash $ git diff 1b6d "master-2" ``` In each case, the output is a patch that can be applied with `git apply`. Try also: ```bash $ git whatchanged --since="2 weeks ago" ``` Often I’ll browse history with `git` instead, due to its slick photogenic interface, or `tig`, a text-mode interface that works well over slow connections. Alternatively, install a web server, run `git instantweb` and fire up any web browser. ## Exercise Let A, B, C, D be four successive commits where B is the same as A except some files have been removed. We want to add the files back at D. How can we do this? There are at least three solutions. Assuming we are at D: 1. The difference between A and B are the removed files. We can create a patch representing this difference and apply it: ```bash $ git diff B A | git apply ``` 2. Since we saved the files back at A, we can retrieve them: ```bash $ git checkout A -- foo.c bar.h ``` 3. We can view going from A to B as a change we want to undo: ```bash $ git revert B ``` Which choice is best? Whichever you prefer most. It is easy to get what you want with Git, and often there are many ways to get it. #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 10 Context: # Cloning Around In older version control systems, checkout is the standard operation to get files. You retrieve a bunch of files in a particular saved state. In Git and other distributed version control systems, cloning is the standard operation. To get files, you create a clone of the entire repository. In other words, you practically mirror the central server. Anything the main repository can do, you can do. ## Sync Computers I can tolerate making tarballs or using `rsync` for backups and basic syncing. But sometimes I edit on my laptop, other times on my desktop, and the two may not have talked to each other in between. 1. Initialize a Git repository and commit your files on one machine. Then on the other: ``` $ git clone other.computer:/path/to/files ``` To create a second copy of the files and Git repository. From now on, run: ``` $ git commit -a $ git pull other.computer:/path/to/files HEAD ``` This will pull in the state of the files on the other computer into the one you’re working on. If you’ve recently made conflicting edits in the same file, Git will let you know and you should commit again after resolving them. ## Classic Source Control Initialize a Git repository for your files: ``` $ git init $ git add . $ git commit -m "Initial commit" ``` On the central server, initialize a bare repository in some directory: ``` $ mkdir proj.git $ cd proj.git $ git --bare init $ touch proj.git/git-daemon-export-ok ``` Start the Git daemon if necessary: ``` $ git daemon --detach # it may already be running ``` For Git hosting services, follow the instructions to set up the initially empty Git repository. Typically one fills in a form on a webpage. Push your project to the central server with: ``` # Command to push instructions (not provided in the original text) ``` #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 11 Context: ``` $ git push central.server/path/to/proj.git HEAD To check out the source, a developer types: ```bash $ git clone central.server/path/to/proj.git ``` After making changes, the developer saves changes locally: ```bash $ git commit -a ``` To update to the latest version: ```bash $ git pull ``` Any merge conflicts should be resolved then committed: ```bash $ git commit -a ``` To check in local changes into the central repository: ```bash $ git push ``` If the main server has new changes due to activity by other developers, the push fails, and the developer should pull the latest version, resolve any merge conflicts, then try again. Developers must have SSH access for the above pull and push commands. However, anyone can see the source by typing: ```bash $ git clone git://central.server/path/to/proj.git ``` The native Git protocol is like HTTP: there is no authentication, so anyone can retrieve the project. Accordingly, by default, pushing is forbidden via the Git protocol. ## Secret Source For a closed-source project, omit the touch command, and ensure you never create a file named `git-daemon-export-ok`. The repository can no longer be retrieved via the Git protocol; only those with SSH access can see it. If all your repos are closed, running the Git daemon is unnecessary because all communication occurs via SSH. ## Bare Repositories A bare repository is so named because it has no working directory: it only contains files that are normally hidden away in the `.git` subdirectory. In other words, it maintains the history of a project and never holds a snapshot of any given version. A bare repository plays a role similar to that of the main server in a centralized version control system: the home of your project. Developers clone your project from it and push the latest official changes to it. Typically, it resides on a server. ``` #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 12 Context: # Git Management Guide ## Push versus Pull Why did we introduce the push command, rather than rely on the familiar pull command? Firstly, pulling fails on bare repositories; instead, you must fetch, a command we will later discuss. But even if we kept a normal repository on the central server, pulling into it would still be cumbersome. We would have to log in to the server first, and give the pull command the network address of the machine we’re pulling from. Firewalls may interfere, and what if we have no shell access to the server in the first place? However, apart from this case, we discourage pushing into a repository because confusion can ensue when the destination has a working directory. In short, while learning Git, only push when the target is a bare repository; otherwise, pull. ## Forking a Project Sick of the way a project is being run? Think you could do a better job? Then on your server: ```bash $ git clone git://main.server/path/to/files ``` Next, tell everybody about your fork of the project at your server. At any later time, you can merge in the changes from the original project with: ```bash $ git pull ``` ## Ultimate Backups Want numerous tamper-proof, geographically diverse redundant archives? If your project has many developers, don’t do anything! Every clone of your code is effectively a backup. Not just of the current state, but of your project’s entire history. Thanks to cryptographic hashing, if anyone's clone becomes corrupted, it will be spotted as soon as they try to communicate with others. If your project is not so popular, find as many servers as you can to lost clones. The truly paranoid should always write down the latest 20-byte SHA1 hash of the HEAD somewhere safe. It has to be safe, not private. For example, publishing it in a newspaper would work well, because it’s hard for an attacker to alter every copy of a newspaper. #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 13 Context: # Light-Speed Multitask Say you want to work on several features in parallel. Then commit your project and run: ``` git clone ./some/new/directory ``` Thanks to hardlinking, local clones require less time and space than a plain backup. You can now work on two independent features simultaneously. For example, you can edit one clone while the other is compiling. At any time, you can commit and pull changes from the other clone: ``` git pull /the/other/clone HEAD ``` # Guerilla Version Control Are you working on a project that uses some other version control system, and you sorely miss Git? Then initialize a Git repository in your working directory: ``` git init git add . git commit -m "Initial commit" ``` Then clone it: ``` git clone ./some/new/directory ``` Now go to the new directory and work here instead, using Git to your heart's content. Once in a while, you'll want to sync with everyone else, in which case go to the original directory, sync using the other version control system, and type: ``` git add . git commit -m "Sync with everyone else" ``` Then go to the new directory and run: ``` git commit -a -m "Description of my changes" git pull ``` The procedure for giving your changes to everyone else depends on the other version control system. The new directory contains the files with your changes. Run whatever commands of the other version control system are needed to upload them to the central repository. Subversion, perhaps the best centralized version control system, is used by countless projects. The `git svn` command automates the above for Subversion repositories and can also be used to export a Git project to a Subversion repository. #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 14 Context: # Mercurial Mercurial is a similar version control system that can almost seamlessly work in tandem with Git. With the `hg-git` plugin, a Mercurial user can losslessly push to and pull from a Git repository. ## Obtain the `hg-git` Plugin with Git: ```bash $ git clone git://github.com/schacon/hg-git.git ``` or Mercurial: ```bash $ hg clone http://bitbucket.org/durin42/hg-git/ ``` Sadly, I am unaware of an analogous plugin for Git. For this reason, I advocate Git over Mercurial for the main repository, even if you prefer Mercurial. With a Mercurial project, usually a volunteer maintains a parallel Git repository to accommodate Git users, whereas thanks to the `hg-git` plugin, a Git project automatically accommodates Mercurial users. Although the plugin can convert a Mercurial repository to a Git repository by pushing to an empty repository, this job is easier with the `hg-fast-export.sh` script, available from: ```bash $ git clone git://repo.or.cz/fast-export.git ``` To convert, in an empty directory: ```bash $ git init $ hg-fast-export.sh -r /hg/repo ``` After adding the script to your `$PATH`. # Bazaar We briefly mention Bazaar because it is the most popular free distributed version control system after Git and Mercurial. Bazaar has the advantage of hindsight, as it is relatively young; its designers could learn from mistakes of the past, and sidestep minor historical warts. Additionally, its developers are mindful of portability and interoperation with other version control systems. A `bzr-git` plugin lets Bazaar users work with Git repositories to some extent. The tailor program converts Bazaar repositories to Git repositories, and can do so incrementally, while `bzr-fast-export` is well-suited for one-shot conversions. # Why I Use Git I originally chose Git because I heard it could manage the unimaginably unmanageable Linux kernel source. I've never felt a need to switch. Git has served #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 15 Context: # Branch Wizardry Instant branching and merging are the most lethal of Git's killer features. ## Problem External factors inevitably necessitate context switching. A severe bug manifests in the released version without warning. The deadline for a certain feature is moved closer. A developer whose help you need for a key section of the project is about to leave. In all cases, you must abruptly drop what you are doing and focus on a completely different task. Interrupting your train of thought can be detrimental to your productivity, and the more cumbersome it is to switch contexts, the greater the loss. With centralized version control, we must download a fresh working copy from the central server. Distributed systems fare better, as we can clone the desired version locally. But cloning still entails copying the whole working directory as well as the entire history up to the given point. Even though Git reduces the cost of this with file sharing and hard links, the project files themselves must be recreated in their entirety in the new working directory. ## Solution Git has a better tool for these situations that is much faster and more space-efficient than cloning: `git branch`. With this magic word, the files in your directory suddenly shapeshift from one version to another. This transformation can do more than merely go back or forward in history. Your files can morph from the last release to the experimental version to the current development version to your friend’s version and so on. # The Boss Key Ever played one of those games where at the push of a button (“the boss key”), the screen would instantly display a spreadsheet or something? So if the boss walked into the office while you were playing the game you could quickly hide it away? #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 16 Context: In some directory: ```bash $ echo "I'm smarter than my boss" > myfile.txt $ git init $ git add . $ git commit -m "Initial commit" ``` We have created a Git repository that tracks one text file containing a certain message. Now type: ```bash $ git checkout -b boss # nothing seems to change after this $ echo "My boss is smarter than me" > myfile.txt $ git commit -a -m "Another commit" ``` It looks like we’ve just overwritten our file and committed it. But it’s an illusion. Type: ```bash $ git checkout master # switch to original version of the file ``` And hey presto! The text file is restored. And if the boss decides to snoop around this directory, type: ```bash $ git checkout boss # switch to version suitable for boss' eyes ``` You can switch between the two versions of the file as much as you like, and commit to each independently. ### Dirty Work Say you're working on some feature, and for some reason, you need to go back three versions and temporarily put in a few print statements to see how something works. Then: ```bash $ git commit -a $ git checkout HEAD~3 ``` Now you can add ugly temporary code all over the place. You can even commit these changes. When you're done, type: ```bash $ git checkout master ``` to return to your original work. Observe that any uncommitted changes are carried over. What if you wanted to save the temporary changes after all? Easy: ```bash $ git checkout -b dirty ``` And commit before switching back to the master branch. Whenever you want to return to the dirty changes, simply type: ```bash $ git checkout dirty ``` #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 17 Context: We touched upon this command in an earlier chapter, when discussing loading old states. At last we can tell the whole story: the files change to the requested state, but we must leave the master branch. Any commits made from now on can take your files down a different road, which can be named later. In other words, after checking out an old state, Git automatically puts you in a new, unnamed branch, which can be named and saved with `git checkout -b`. ## Quick Fixes You’re in the middle of something when you are told to drop everything and fix a newly discovered bug in commit 186d...: ```bash $ git commit -a $ git checkout -b fixes 186d ``` Then once you’ve fixed the bug: ```bash $ git commit -a -m "Bug fixed" $ git checkout master ``` And resume work on your original task. You can even merge in the freshly baked bugfix: ```bash $ git merge fixes ``` ## Merging With some version control systems, creating branches is easy but merging them back together is tough. With Git, merging is so trivial that you might be unaware of it happening. We actually encountered merging long ago. The `pull` command in fact fetches commits and then merges them into your current branch. If you have no local changes, then the merge is a fast forward, a degenerate case akin to fetching the latest version in a centralized version control system. But if you do have local changes, Git will automatically merge and report any conflicts. Ordinarily, a commit has exactly one parent commit, namely, the previous commit. Merging branches together produces a commit with at least two parents. This begs the question: what commit does `HEAD~1` really refer to? A commit could have multiple parents, so which one do we follow? It turns out this notation chooses the first parent every time. This is desirable because the current branch becomes the first parent during a merge; frequently you’re only concerned with the changes you made in the current branch, as opposed to changes merged in from other branches. You can refer to a specific parent with a caret. For example, to show the logs from the second parent: #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 18 Context: ``` $ git log HEAD~2 You may omit the number for the first parent. For example, to show the differences with the first parent: $ git diff HEAD~ You can combine this notation with other types. For example: $ git checkout 16bd~2-10 -b ancient starts a new branch “ancient” representing the state 10 commits back from the second parent of the first parent of the commit starting with 16bd. ## Uninterrupted Workflow Often in hardware projects, the second step of a plan must await the completion of the first step. A car undergoing repairs might sit idly in a garage until a particular part arrives from the factory. A prototype might wait for a chip to be fabricated before construction can continue. Software projects can be similar. The second part of a new feature may have to wait until the first part has been released and tested. Some projects require your code to be reviewed before accepting it, so you might wait until the first part is approved before starting the second part. Thanks to painless branching and merging, we can bend the rules and work on Part II before Part I is officially ready. Suppose you have committed Part I and sent it for review. Let’s say you’re in the `master` branch. Then branch off: $ git checkout -b part2 Next, work on Part II, committing your changes along the way. To err is human, and often you’ll want to go back and fix something in Part I. If you’re lucky, or very good, you can skip these lines: ```bash $ git checkout master # Go back to Part I. $ fix_problem $ git commit -a # Commit the fixes. $ git checkout part2 # Go back to Part II. $ git merge master # Merge in those fixes. ``` Eventually, Part I is approved: ```bash $ git checkout master # Go back to Part I. $ submit files # Release to the world! $ git merge part2 # Merge in Part II. $ git branch -d part2 # Delete "part2" branch. ``` Now you’re in the `master` branch again, with Part II in the working directory. ``` #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 19 Context: It's easy to extend this trick for any number of parts. It's also easy to branch off retroactively; suppose you belatedly realize you should have created a branch 7 commits ago. Then type: ```bash git branch -m master part2 # Rename "master" branch to "part2". git branch master HEAD~7 # Create new "master," 7 commits upstream. ``` The master branch now contains just Part I, and the part2 branch contains the rest. We are in the latter branch; we created master without switching to it, because we want to continue work on part2. This is unusual. Until now, we've been switching to branches immediately after creation, as in: ```bash git checkout HEAD~7 -b master # Create a branch, and switch to it. ``` ## Reorganizing a Medley Perhaps you like to work on all aspects of a project in the same branch. You want to keep works-in-progress to yourself and want others to see your commits only when they have been neatly organized. Start a couple of branches: ```bash git branch sanitized # Create a branch for sanitized commits. git checkout -b medley # Create and switch to a branch to work in. ``` Next, work on anything: fix bugs, add features, add temporary code, and so forth, committing often along the way. Then: ```bash git checkout sanitized # Switch back to the sanitized branch. git cherry-pick medley # Apply commits from medley to sanitized. ``` This applies the grandparent of the head commit of the "medley" branch to the "sanitized" branch. With appropriate cherry-picks, you can construct a branch that contains only permanent code and has related commits grouped together. ## Managing Branches List all branches by typing: ```bash git branch ``` By default, you start in a branch named "master." Some advocate leaving the "master" branch untouched and creating new branches for your own edits. The `-d` and `-m` options allow you to delete and move (rename) branches. See `git help branch`. The "master" branch is a useful custom. Others may assume that your repository has a branch with this name and that it contains the official version of your project. Although you can rename or obliterate the "master" branch, you might as well respect this convention. #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 20 Context: # Temporary Branches After a while, you may realize you are creating short-lived branches frequently for similar reasons: every other branch merely serves to save the current state so you can briefly hop back to an older state to fix a high-priority bug or something. It’s analogous to changing the TV channel temporarily to see what else is on. But instead of pushing a couple of buttons, you have to create, check out, merge, and delete temporary branches. Luckily, Git has a shortcut that is as convenient as a TV remote control: ``` $ git stash ``` This saves the current state in a temporary location (a stash) and restores the previous state. Your working directory appears exactly as it was before you started editing, and you can fix bugs, pull in upstream changes, and so on. When you want to go back to the stashed state, type: ``` $ git stash apply # You may need to resolve some conflicts. ``` You can have multiple stashes and manipulate them in various ways. See `git help stash`. As you may have guessed, Git maintains branches behind the scenes to perform this magic trick. # Work How You Want You might wonder if branches are worth the bother. After all, `clones` are almost as fast, and you can switch between them with `cd` instead of esoteric Git commands. Consider web browsers. Why support multiple tabs as well as multiple windows? Because allowing both accommodates a wide variety of styles. Some users like to keep only one browser window open, and use tabs for multiple webpages. Others might insist on the other extreme: multiple windows with no tabs anywhere. Others still prefer something in between. Branching is like tabs for your working directory, and cloning is like opening a new browser window. These operations are fast and local, so why not experiment to find the combination that best suits you? Git lets you work exactly how you want. # Lessons of History A consequence of Git’s distributed nature is that history can be edited easily. But if you tamper with the past, take care: only rewrite that part of history which you alone possess. Just as nations forever argue over who committed what atrocity, if someone else has a clone whose version of history differs to yours, you will have trouble reconciling when your trees interact. #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 21 Context: Some developers strongly feel history should be immutable, warts and all. Others feel trees should be made presentable before they are unleashed in public. Git accommodates both viewpoints. Like cloning, branching, and merging, rewriting history is simply another power Git gives you. It is up to you to use it wisely. # I Stand Corrected Did you just commit, but wish you had typed a different message? Then run: ``` $ git commit --amend ``` to change the last message. Realized you forgot to add a file? Run `git add` to add it, and then run the above command. Want to include a few more edits in that last commit? Then make those edits and run: ``` $ git commit --amend -a ``` ## ... And Then Some Suppose the previous problem is ten times worse. After a lengthy session you've made a bunch of commits. But you're not quite happy with the way they're organized, and some of those commit messages could use rewording. Then type: ``` $ git rebase -i HEAD~10 ``` and the last 10 commits will appear in your favourite `$EDITOR`. A sample excerpt: ``` pick 56be673 Added repo.or.cz link pick a311a64 Reordered analogies in "Work How You Want" pick 100834f Added push target to Makefile ``` Older commits precede newer commits in this list, unlike the log command. Here, `56be673` is the oldest commit, and `100834f` is the newest. Then: - Remove commits by deleting lines. Like the revert command, but off the record: it will be as if the commit never existed. - Reorder commits by reordering lines. Replace `pick` with: - `edit` to mark a commit for amending. - `reword` to change the log message. - `squash` to merge a commit with the previous one. - `fixup` to merge a commit with the previous one and discard the log message. #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 22 Context: For example, we might replace the second pick with squash: ``` pick 5c6b673 Added repo.or.cz link squash a311a6a Reordered analogies in "Work How You Want" pick 100384f Added push target to Makefile ``` After we save and quit, Git merges a311a6a into 5c6b673. Thus, squash merges into the next commit up: think “squash up”. Git then combines their log messages and presents them for editing. The command `fixup` skips this step; the squashed log message is simply discarded. If you marked a commit with `edit`, Git returns you to the past, to the oldest such commit. You can amend the old commit as described in the previous section, and even create new commits that belong here. Once you’re pleased with the “recton”, go forward in time by running: ```bash $ git rebase --continue ``` Git replays commits until the next edit, or to the present if none remain. You can also abandon the rebase with: ```bash $ git rebase --abort ``` So commit early and commit often: you can tidy up later with rebase. ## Local Changes Last You’re working on an active project. You make some local commits over time, and then you sync with the official tree in a merge. This cycle repeats itself a few times before you’re ready to push to the central tree. But now the history in your local Git clone is a messy jumble of your changes and the official changes. You’d prefer to see all your changes in one contiguous section, and after all the official changes. This is a job for `git rebase` as described above. In many cases you can use the `--onto` flag and avoid interaction. Also see `git help rebase` for detailed examples of this amazing command. You can split commits. You can even rearrange branches of a tree. Take care: `rebase` is a powerful command. For complicated rebases, first make a backup with `git clone`. ## Rewriting History Occasionally, you need the source control equivalent of airbrushing people out of official photos, erasing them from history in a Stalin-esque fashion. For example, suppose we intend to release a project, but it involves a file that should be kept private for some reason. Perhaps I left my credit card number in a text file and #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 23 Context: # Making History Want to migrate a project to Git? If it’s managed with one of the more well-known systems, then chances are someone has already written a script to export the whole history to Git. Otherwise, look up `git fast-import`, which reads text input in a specific format to create Git history from scratch. Typically a script using this command is hastily cobbled together and run once, migrating the project in a single shot. As an example, paste the following listing into a temporary file, such as `/tmp/history`: ``` commit refs/heads/master committer Alice Thu, 01 Jan 1970 00:00:00 +0000 data < int main() { printf("Hello, World!\\n"); return 0; } EOT commit refs/heads/master committer Bob Tue, 14 Mar 2000 01:59:26 -0800 data < #include int main() { write(1, "Hello, world!\n", 14); return 0; } ``` Then create a Git repository from this temporary file by typing: ```bash $ mkdir project; cd project; git init $ git fast-import --date-format=rfc2822 < /tmp/history ``` You can checkout the latest version of the project with: ```bash $ git checkout master ``` The `git fast-export` command converts any repository to the `git fast-import` format, whose output you can study for writing exporters, and also to transport repositories in a human-readable format. Indeed, these commands can send repositories of text files over text-only channels. ## Where Did It All Go Wrong? You've just discovered a broken feature in your program which you know for sure was working a few months ago. Argh! Where did this bug come from? If only you had been testing the feature as you developed. It's too late for that now. However, provided you've been committing often, Git can pinpoint the problem: ```bash $ git bisect start $ git bisect bad HEAD $ git bisect good b16d ``` Git checks out a state halfway in between. Test the feature, and if it’s still broken: ```bash $ git bisect bad ``` If not, replace "bad" with "good". Git again transports you to a state halfway between the known good and bad versions, narrowing down the possibilities. After a few iterations, this binary search will lead you to the commit that caused the trouble. Once you’ve finished your investigation, return to your original state by typing: ```bash $ git bisect reset ``` #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 25 Context: ``` $ git bisect reset Instead of testing every change by hand, automate the search by running: $ git bisect run my_script Git uses the return value of the given command, typically a one-off script, to decide whether a change is good or bad: the command should exit with code 0 when good, 125 when the change should be skipped, and anything else between 1 and 127 if it is bad. A negative return value aborts the bisect. You can do much more: the help page explains how to visualize bisects, examine or replay the bisect log, and eliminate known innocent changes for a speedier search. ## Who Made It All Go Wrong? Like many other version control systems, Git has a blame command: $ git blame bug.c which annotates every line in the given file showing who last changed it, and when. Unlike many other version control systems, this operation works offline, reading only from local disk. ## Personal Experience In a centralized version control system, history modification is a difficult operation, and only available to administrators. Cloning, branching, and merging are impossible without network communication. So are basic operations such as browsing history, or committing a change. In some systems, users require network connectivity just to view their own changes or open a file for editing. Centralized systems preclude working offline, and need more expensive network infrastructure, especially as the number of developers grows. Most importantly, all operations are slower to some degree, usually to the point where users shun advanced commands unless absolutely necessary. In extreme cases this is true of even the most basic commands. When users must run slow commands, productivity suffers because of an interrupted work flow. I experienced these phenomena first-hand. Git was the first version control system I used. I quickly grew accustomed to it, taking many features for granted. I simply assumed other systems were similar; choosing a version control system ought to be no different from choosing a text editor or web browser. I was shocked when later forced to use a centralized system. A flaky internet connection matters little with Git, but makes development unbearable when it needs to be as reliable as local disk. Additionally, I found myself conditioned to avoid certain commands because of the latencies involved, which ultimately prevented me from following my desired work flow. ``` #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 26 Context: When I had to run a slow command, the interruption to my train of thought dealt a disproportionate amount of damage. While waiting for server communication to complete, I'd do something else to pass the time, such as check email or write documentation. By the time I returned to the original task, the command had finished long ago, and I would waste more time trying to remember what I was doing. Humans are bad at context switching. There was also an interesting tragedy of the commons effect: anticipating network congestion, individuals would consume more bandwidth than necessary on various operations in an attempt to reduce future delays. The combined efforts intensified congestion, encouraging individuals to consume even more bandwidth next time to avoid even longer delays. ## Multiplayer Git Initially I used Git on a private project where I was the sole developer. Amongst the commands related to Git's distributed nature, I needed only pull and clone so I could keep the same project in different places. Later I wanted to publish my code with Git and include changes from contributors. I had to learn how to manage projects with multiple developers from all over the world. Fortunately, this is Git's forte, and arguably its raison d'être. ## Who Am I? Every commit has an author name and email, which is shown by `git log`. By default, Git uses system settings to populate these fields. To set them explicitly, type: ```bash $ git config --global user.name "John Doe" $ git config --global user.email johndoe@example.com ``` Omit the global flag to set these options only for the current repository. ## Git Over SSH, HTTP Suppose you have SSH access to a web server, but Git is not installed. Though less efficient than its native protocol, Git can communicate over HTTP. Download, compile and install Git in your account, and create a repository in your web directory: ```bash $ GIT_DIR=proj.git git init $ cd proj.git $ git --bare update-server-info $ cp hooks/post-update.sample hooks/post-update ``` For older versions of Git, the copy command fails and you should run: #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 27 Context: ```markdown $ chmod +x hooks/post-update Now you can publish your latest edits via SSH from any clone: ``` $ git push web.server:/path/to/proj.git master ``` and anybody can get your project with: ``` $ git clone http://web.server/proj.git ``` ## Git Over Anything Want to synchronize repositories without servers, or even a network connection? Need to improvise during an emergency? We’ve seen `git fast-export` and `git fast-import` can convert repositories to a single file and back. We could shuttle such files back and forth to transport git repositories over any medium, but a more efficient tool is `git bundle`. ### The sender creates a bundle: ``` $ git bundle create somefile HEAD ``` then transports the bundle, `somefile`, to the other party somehow: email, thumb drive, an xxd printout and an OCR scanner, reading bits over the phone, smoke signals, etc. The receiver retrieves commits from the bundle by typing: ``` $ git pull somefile ``` The receiver can even do this from an empty repository. Despite its size, `somefile` contains the entire original git repository. In larger projects, eliminate waste by bundling only changes the other repository lacks. For example, suppose the commit `1b6d...` is the most recent commit shared by both parties: ``` $ git bundle create somefile HEAD "1b6d" ``` If done frequently, one could easily forget which commit was last sent. The help page suggests using tags to solve this. Namely, after you send a bundle, type: ``` $ git tag -f lastbundle HEAD ``` and create new refresher bundles with: ``` $ git bundle create newbundle HEAD ^lastbundle ``` ## Patches: The Global Currency Patches are text representations of your changes that can be easily understood by computers and humans alike. This gives them universal appeal. You can email a patch to developers no matter what version control system they’re using. As long as your audience can read their email, they can see your edits. Similarly, ``` #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 28 Context: # Working with Patches in Git On your side, all you require is an email account: there’s no need to set up an online Git repository. ## Recall from the First Chapter: ```bash $ git diff 1b6d > my.patch ``` This outputs a patch which can be pasted into an email for discussion. In a Git repository, type: ```bash $ git apply < my.patch ``` to apply the patch. In more formal settings, when author names and perhaps signatures should be recorded, generate the corresponding patches past a certain point by typing: ```bash $ git format-patch 1b6d ``` The resulting files can be given to `git-send-email`, or sent by hand. You can also specify a range of commits: ```bash $ git format-patch 1b6d..HEAD ``` On the receiving end, save an email to a file, then type: ```bash $ git am < email.txt ``` This applies the incoming patch and also creates a commit, including information such as the author. With a browser email client, you may need to click a button to see the email in its raw original form before saving the patch to a file. There are slight differences for mbox-based email clients, but if you use one of these, you’re probably the sort of person who can figure them out easily without reading tutorials. ## Sorry, We’ve Moved After cloning a repository, running `git push` or `git pull` will automatically push to or pull from the original URL. How does Git do this? The secret lies in config options created with the clone. Let’s take a peek: ```bash $ git config --list ``` The `remote.origin.url` option controls the source URL; “origin” is a nickname given to the source repository. As with the “master” branch convention, we may change or delete this nickname but there is usually no reason for doing so. If the original repository moves, we can update the URL via: ```bash $ git config remote.origin.url git://new.url/proj.git ``` #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 29 Context: The branch `master.merge` option specifies the default remote branch in a `git pull`. During the initial clone, it is set to the current branch of the source repository, so even if the HEAD of the source repository subsequently moves to a different branch, a later pull will faithfully follow the original branch. This option only applies to the repository we first cloned from, which is recorded in the option `branch.master.remote`. If we pull in from other repositories, we must explicitly state which branch we want: ```bash $ git pull git://example.com/other.git master ``` The above explains why some of our earlier push and pull examples had no arguments. ## Remote Branches When you clone a repository, you also clone all its branches. You may not have noticed this because Git hides them away; you must ask for them specifically. This prevents branches in the remote repository from interfering with your branches and also makes Git easier for beginners. List the remote branches with: ```bash $ git branch -r ``` You should see something like: ``` origin/HEAD origin/master origin/experimental ``` These represent branches and the HEAD of the remote repository and can be used in regular Git commands. For example, suppose you have made many commits and wish to compare against the last fetched version. You could search through the logs for the appropriate SHA1 hash, but it’s much easier to type: ```bash $ git diff origin/HEAD ``` Or you can see what the “experimental” branch has been up to: ```bash $ git log origin/experimental ``` ## Multiple Remotes Suppose two other developers are working on our project, and we want to keep tabs on both. We can follow more than one repository at a time with: ```bash $ git remote add other git://example.com/some_repo.git $ git pull other some_branch ``` Now we have merged in a branch from the second repository, and we have easy access to all branches of all repositories: #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 30 Context: ```markdown $ git diff origin/experimental* other/some_branch-5 But what if we just want to compare their changes without affecting our own work? In other words, we want to examine their branches without having their changes invade our working directory. Then rather than pull, run: ```bash $ git fetch # Fetch from origin, the default. $ git fetch other # Fetch from the second programmer. ``` This just fetches histories. Although the working directory remains untouched, we can refer to any branch of any repository in a Git command because we now possess a local copy. Recall that behind the scenes, a pull is simply a fetch then merge. Usually we pull because we want to merge the latest commit after a fetch; this situation is a notable exception. See `git help remote` for how to remove remote repositories, ignore certain branches, and more. ## My Preferences For my projects, I like contributors to prepare repositories from which I can pull. Some Git hosting services let you host your own fork of a project with the click of a button. After I fetch a tree, I run Git commands to navigate and examine the changes, which ideally are well-organized and well-described. I merge my own changes and perhaps make further edits. Once satisfied, I push to the main repository. Though I infrequently receive contributions, I believe this approach scales well. See this [blog post by Linus Torvalds](https://example.com). Staying in the Git world is slightly more convenient than patch files, as it saves me from converting them to Git commits. Furthermore, Git handles details such as recording the author’s name and email address, as well as the time and date, and asks the author to describe their own change. ## Git Grandmastery By now, you should be able to navigate the `git help` pages and understand almost everything. However, pinpointing the exact command required to solve a given problem can be tedious. Perhaps I can save you some time; below are some recipes I have needed in the past. ## Source Releases For my projects, Git tracks exactly the files I’d like to archive and release to users. To create a tarball of the source code, I run: ```bash ``` ``` #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 31 Context: ``` $ git archive --format=tar --prefix=proj-1.2.3/ HEAD # Commit What Changed Telling Git when you’ve added, deleted and renamed files is troublesome for certain projects. Instead, you can type: ```bash $ git add . $ git add -u ``` Git will look at the files in the current directory and work out the details by itself. Instead of the second add command, run `git commit -a` if you also intend to commit at this time. See `git help ignore` for how to specify files that should be ignored. You can perform the above in a single pass with: ```bash $ git ls-files -d -o -z | xargs -0 git update-index --add --remove ``` The `-z` and `-o` options prevent ill side-effects from filenames containing strange characters. As this command adds ignored files, you may want to use the `-x` or `-X` option. # My Commit Is Too Big! Have you neglected to commit for too long? Been coding furiously and forgotten about source control until now? Made a series of unrelated changes, because that’s your style? No worries. Run: ```bash $ git add -p ``` For each edit you make, Git will show you the hunk of code that was changed, and ask if it should be part of the next commit. Answer with “y” or “n”. You have other options, such as postponing the decision; type “?” to learn more. Once you’re satisfied, type: ```bash $ git commit ``` to commit precisely the changes you selected (the staged changes). Make sure you omit the `-a` option, otherwise Git will commit all the edits. What if you’ve edited many files in many places? Reviewing each change one by one becomes frustratingly mind-numbing. In this case, use `git add -i`, whose interface is less straightforward, but more flexible. With a few keystrokes, you can stage or unstage several files at a time, or review and select changes in particular files only. Alternatively, run `git commit --interactive` which automatically commits after you’re done. ``` #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 32 Context: # The Index: Git’s Staging Area So far we have avoided Git's famous `index`, but we must now confront it to explain the above. The index is a temporary staging area. Git seldom shuttles data directly between your project and its history. Rather, Git first writes data to the index, and then copies the data in the index to its final destination. For example, `commit -a` is really a two-step process. The first step places a snapshot of the current state of every tracked file into the index. The second step permanently records the snapshot now in the index. Committing without the `-a` option only performs the second step, and only makes sense after running commands that somehow change the index, such as `git add`. Usually, we can ignore the index and pretend we are reading straight from and writing straight to the history. On this occasion, we want finer control, so we manipulate the index. We place a snapshot of some, but not all, of our changes into the index, and then permanently record this carefully rigged snapshot. ## Don’t Lose Your HEAD The `HEAD` tag is like a cursor that normally points at the latest commit, advancing with each new commit. Some Git commands let you move it. For example: ```bash $ git reset HEAD~3 ``` will move the `HEAD` three commits back. Thus all Git commands now act as if you hadn't made those last three commits, while your files remain in the present. See the help page for some applications. But how can you go back to the future? The past commits know nothing of the future. If you have the SHA1 of the original HEAD then: ```bash $ git reset 1b6a ``` But suppose you never took it down? Don’t worry: for commands like these, Git saves the original `HEAD` as a tag called `ORIG_HEAD`, and you can return safe and sound with: ```bash $ git reset ORIG_HEAD ``` ## HEAD-hunting Perhaps `ORIG_HEAD` isn’t enough. Perhaps you’ve just realized you made a monumental mistake and you need to go back to an ancient commit in a long-forgotten branch. By default, Git keeps a commit for at least two weeks, even if you ordered Git to destroy the branch containing it. The trouble is finding the appropriate hash. #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 33 Context: You could look at all the hash values in `.git/objects` and use trial and error to find the one you want. But there's a much easier way. Git records every hash of a commit it computes in `.git/logs`. The subdirectory `refs` contains the history of all activity on all branches, while the file `HEAD` shows every hash value it has ever taken. The latter can be used to find hashes of commits on branches that have been accidentally lopped off. The `git reflog` command provides a friendly interface to these log files. Try: ```bash $ git reflog ``` Instead of cutting and pasting hashes from the reflog, try: ```bash $ git checkout "@{10 minutes ago}" ``` Or checkout the 5th-last visited commit via: ```bash $ git checkout "@{5}" ``` See the “Specifying Revisions” section of `git help rev-parse` for more. You may wish to configure a longer grace period for doomed commits. For example: ```bash $ git config gc.pruneexpire "30 days" ``` means a deleted commit will only be permanently lost once 30 days have passed and `git gc` is run. You may also wish to disable automatic invocations of `git gc`: ```bash $ git config gc.auto 0 ``` in which case commits will only be deleted when you run `git gc` manually. ## Building On Git In true UNIX fashion, Git's design allows it to be easily used as a low-level component of other programs, such as GUI and web interfaces, alternative command-line interfaces, patch management tools, importing and conversion tools, and so on. In fact, some Git commands are themselves scripts standing on the shoulders of giants. With a little tinkering, you can customize Git to suit your preferences. One easy trick is to use built-in Git aliases to shorten your most frequently used commands: ```bash $ git config --global alias.co checkout $ git config --global --get-regexp alias # display current aliases ``` ```bash alias.co checkout ``` ```bash $ git co foo # same as 'git checkout foo' ``` Another is to print the current branch in the prompt or window title. Invoking #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 34 Context: ``` $ git symbolic-ref HEAD shows the current branch name. In practice, you most likely want to remove the `refs/heads/` and ignore errors: ```bash $ git symbolic-ref HEAD 2> /dev/null | cut -b 12- ``` The `contrib` subdirectory is a treasure trove of tools built on Git. In time, some of them may be promoted to official commands. On Debian and Ubuntu, this directory lives at `/usr/share/doc/git-core/contrib`. One popular resident is `workdir/git-new-workdir`. Via clever symlinking, this script creates a new working directory whose history is shared with the original repository: ```bash $ git-new-workdir an/existing/repo new/directory ``` The new directory and the files within can be thought of as a clone, except since the history is shared, the two trees automatically stay in sync. There's no need to merge, push, or pull. ## Daring Stunts These days, Git makes it difficult for the user to accidentally destroy data. But if you know what you are doing, you can override safeguards for common commands. ### Checkout Uncommitted changes cause checkout to fail. To destroy your changes, and checkout a given commit anyway, use the force flag: ```bash $ git checkout -f HEAD ``` On the other hand, if you specify particular paths for checkout, then there are no safety checks. The supplied paths are quietly overwritten. Take care if you use checkout in this manner. ### Reset Reset also fails in the presence of uncommitted changes. To force it through, run: ```bash $ git reset --hard 16d ``` ### Branch Deleting branches fails if this causes changes to be lost. To force a deletion, type: ```bash $ git branch -D dead_branch # instead of -d ``` Similarly, attempting to overwrite a branch via a move fails if data loss would ensue. To force a branch move, type: ```bash $ git branch -M source target # instead of -m ``` Unlike checkout and reset, these two commands defer data destruction. The changes are still stored in the `.git` subdirectory, and can be retrieved by `recover`. ``` #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 35 Context: # Preventing Bad Commits Stupid mistakes pollute my repositories. Most frightening are missing files due to a forgotten `git add`. Lesser transgressions are trailing whitespace and unresolved merge conflicts; though harmless, I wish these never appeared on the public record. If only I had bought idiot insurance by using a hook to alert me about these problems: ```bash $ cd .git/hooks $ cp pre-commit.sample pre-commit # Older Git versions: chmod +x pre-commit ``` Now Git shorts a commit if useless whitespace or unresolved merge conflicts are detected. For this guide, I eventually added the following to the beginning of the `pre-commit` hook to guard against absent-mindedness: ```bash if git ls-files -o | grep '\.txt$'; then echo "FAIL! Untracked .txt files." exit 1 fi ``` Several git operations support hooks; see `git help hooks`. We activated the sample `post-update` hook earlier when discussing Git over HTTP. This runs whenever the head moves. The sample `post-update` script updates files Git needs for communication over Git-agnostic transports such as HTTP. # Secrets Revealed We take a peek under the hood and explain how Git performs its miracles. I will skimp over details. For in-depth descriptions refer to the user manual. ## Invisibility How can Git be so unobtrusive? Aside from occasional commits and merges, you can work as if you were unaware that version control exists. That is, until #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 36 Context: # Integrity Most people associate cryptography with keeping information secret, but another equally important goal is keeping information safe. Proper use of cryptographic hash functions can prevent accidental or malicious data corruption. A SHA1 hash can be thought of as a unique 160-bit ID number for every string of bytes you'll encounter in your life. Actually more than that: every string of bytes that any human will ever use over many lifetimes. As a SHA1 hash is itself a string of bytes, we can hash strings of bytes containing other hashes. This simple observation is surprisingly useful: look up [hash chains](#). We'll later see how Git uses it to efficiently guarantee data integrity. Briefly, Git keeps your data in the `.git/objects` subdirectory, where instead of formal filenames, you'll find only IDs. By using IDs as filenames, as well as a few lockfiles and timestamping tricks, Git transforms any humble filesystem into an efficient and robust database. --- # Intelligence How does Git know you renamed a file, even though you never mentioned the fact explicitly? Sure, you may have run `git mv`, but that is exactly the same as a `git rm` followed by a `git add`. Git heuristically ferrets out renames and copies between successive versions. In fact, it can detect chunks of code being moved or copied around between files! Though it cannot cover all cases, it does a decent job, and this feature is always improving. If it fails to work for you, try options enabling more expensive copy detection, and consider upgrading. #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 37 Context: # Indexing For every tracked file, Git records information such as its size, creation time, and last modification time in a file known as the index. To determine whether a file has changed, Git compares its current stats with those cached in the index. If they match, then Git can skip reading the file again. Since stat calls are considerably faster than file reads, if you only edit a few files, Git can update its state in almost no time. We stated earlier that the index is a staging area. Why is a bunch of file stats a staging area? Because the `add` command puts files into Git's database and updates these stats, while the `commit` command, without options, creates a commit based only on these stats and the files already in the database. ## Git's Origins This Linux Kernel Mailing List post describes the chain of events that led to Git. The entire thread is a fascinating archaeological site for Git historians. ## The Object Database Every version of your data is kept in the object database, which lives in the subdirectory `.git/objects`; the other residents of `.git` hold lesser data: the index, branch names, tags, configuration options, logs, the current location of the head commit, and so on. The object database is elementary yet elegant, and the source of Git's power. Each file within `.git/objects` is an object. There are 3 kinds of objects that concern us: **blob** objects, **tree** objects, and **commit** objects. ## Blobs First, a magic trick. Pick a filename, any filename. In an empty directory: ```bash $ echo sweet > YOUR_FILENAME $ git init $ git add $ find .git/objects -type f ``` You'll see `.git/objects/a/82372e8e745922cc69b36875a482cd3fd5c8d`. How do I know this without knowing the filename? It’s because the SHA1 hash of: ``` "blob" SP "6" NUL "sweet" LF ``` is `a82372e8e745922cc69b36875a482cd3fd5c8d`, where SP is a space, NUL is a zero byte, and LF is a linefeed. You can verify this by typing: ```bash $ printf "blob 6\000sweet\n" | shasum ``` #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 38 Context: Git is content-addressable: files are not stored according to their filename, but rather by the hash of the data they contain, in a file we call a **blob object**. We can think of the hash as a unique ID for a file's contents, so in a sense we are addressing files by their content. The initial blob is merely a header consisting of the object type and its length in bytes; it simplifies internal bookkeeping. Thus I could easily predict what you would see. The file's name is irrelevant: only the data inside is used to construct the blob object. You may be wondering what happens to identical files. Try adding copies of your file, with any filenames whatsoever. The contents of `.git/objects` stay the same no matter how many you add. Git only stores the data once. By the way, the files within `.git/objects` are compressed with zlib, so you should not stare at them directly. Filter them through `zcat -d`, or type: ```bash git cat-file -p aa823728ea745922cc69368754a82d2df3d5c8d ``` which pretty-prints the given object. ## Trees But where are the filenames? They must be stored somewhere at some stage. Git gets around to the filenames during a commit: ```bash git commit -m "Type some message." find .git/objects -type f ``` You should now see 3 objects. This time I cannot tell you what the 2 new files are, as it partly depends on the filename you picked. We'll proceed assuming you chose *rose*. If you didn’t, you can rewrite history to make it look like you did: ```bash git filter-branch --tree-filter 'mv YOUR_FILENAME rose' find .git/objects -type f ``` Now you should see the file `.git/objects/05/b217b859794d08b9e4f704cbada4207be9` because this is the SHA1 hash of its contents: ``` tree "SP" "32" NULL "100644" NULL 0xa823728ea745922cc69368754a82d2df3d5c8d ``` Check this file does indeed contain the above by typing: ```bash echo 05b217b859794d08b9e4f704cbada4207be9 | git cat-file --batch ``` With zpipe, it's easy to verify the hash: ```bash zpipe -d .git/objects/05/b217b859794d08b9e4f704cbada4207be9 | shasum ``` Hash verification is trickier via `cat-file` because its output contains more than the raw uncompressed object file. This file is a **tree object**: a list of tuples consisting of a file type, a filename, and a hash. In our example, the file type is `100644`, which means *rose* is a normal file. #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 39 Context: # Git Objects and Commits In Git, there are three main types of objects: blob, tree, and commit. The blob object contains the contents of a file, while the tree object contains references to the blobs and other trees. The hash is the blob object that contains the contents of 'rose'. Other possible file types are executables, symlinks, or directories. In the last case, the hash points to a tree object. If you run `git filter-branch`, you'll have old objects you no longer need. Although they will be deleted automatically once the grace period expires, we'll delete them now to make our example easier to follow: ```bash $ rm -r .git/refs/original $ git reflog expire --expire=now --all $ git prune ``` For real projects, you should typically avoid commands like this, as you are destroying backups. If you want a clean repository, it is usually best to make a fresh clone. Also, take care when directly manipulating `.git`; what if a Git command is running at the same time, or a sudden power outage occurs? In general, refs should be deleted with `git update-ref -d`, though usually, it’s safe to remove `refs/original` by hand. ## Commits We’ve explained 2 of the 3 objects. The third is a commit object. Its contents depend on the commit message as well as the date and time it was created. To match what we have here, we’ll have to tweak it a little: ```bash $ git commit --amend --author="Shakespeare" # Change the commit message. $ git filter-branch --new-filter 'export GIT_AUTHOR_DATE="Fri 13 Feb 2009 15:31:30 -0800" GIT_AUTHOR_NAME="Alice" GIT_AUTHOR_EMAIL="alice@example.com" GIT_COMMITTER_DATE="Fri, 13 Feb 2009 15:31:30 -0800" GIT_COMMITTER_NAME="Bob" GIT_COMMITTER_EMAIL="bob@example.com" # Rig timestamps and authors. ' find .git/objects --type f ``` You should now see `.git/objects/49/993fe130c43bf248571a56796396b7cb187`, which is the SHA1 hash of its contents: ``` "commit 158" NUL "encoding 0" LF "tree 05b21b78579740d88b9e941f70c4bd4207fb9" LF "author Alice 1234567890 -0800" LF "committer Bob 1234567890 -0800" LF "Shakespeare" LF ``` As before, you can run `zip` or `cat-file` to see for yourself. This is the first commit, so there are no parent commits, but later commits will always contain at least one line identifying a parent commit. #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 40 Context: # Indistinguishable From Magic Git’s secrets seem so simple. It looks like you could mix together a few shell scripts and add a dash of C code to cook it up in a matter of hours: a melange of basic filesystem operations and SHA1 hashing, garnished with lock files and synops for robustness. In fact, this accurately describes the earliest versions of Git. Nonetheless, apart from ingenious packing tricks to save space, and ingenious indexing tricks to save time, we now know how Git deftly changes a filesystem into a database perfect for version control. For example, if any file within the object database is corrupted by a disk error, then its hash will no longer match, alerting us to the problem. By hashing hashes of other objects, we maintain integrity at all levels. Commits are atomic; that is, a commit can never only partially record changes: we can only compute the hash of a commit and store it in the database after we already have stored all relevant trees, blobs, and parent commits. The object database is immune to unexpected interruptions such as power outages. We defeat even the most devious adversaries. Suppose somebody attempts to stealthily modify the contents of a file in an ancient version of a project. To keep the object database looking healthy, they must also change the hash of the corresponding blob object since it’s now a different string of bytes. This means they’ll have to change the hash of any tree object referencing the file, and in turn change the hash of all commit objects involving such a tree, in addition to the hashes of all the descendants of these commits. This implies the hash of the official head differs from that of the bad repository. By following the trail of mismatching hashes we can pinpoint the mutilated file, as well as the commit where it was first corrupted. In short, so long as the 20 bytes representing the last commit are safe, it’s impossible to tamper with a Git repository. What about Git's famous features? Branching? Merging? Tags? More details. The current head is kept in the file `.git/HEAD`, which contains a hash of a commit object. The hash gets updated during a commit as well as many other commands. Branches are almost the same; there are files in `.git/refs/heads`. Tags too: they live in `.git/refs/tags` but they are updated by a different set of commands. # Git Shortcomings There are some Git issues I’ve swept under the carpet. Some can be handled easily with scripts and hooks, some require reorganizing or redefining the project, and for the few remaining annoyances, one will just have to wait. Or better yet, pitch in and help! #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 41 Context: # SHA1 Weaknesses As time passes, cryptographers discover more and more SHA1 weaknesses. Already, finding hash collisions is feasible for well-funded organizations. Within years, perhaps even a typical PC will have enough computing power to silently corrupt a Git repository. Hopefully, Git will migrate to a better hash function before further research destroys SHA1. ## Microsoft Windows Git on Microsoft Windows can be cumbersome: - **Cygwin**, a Linux-like environment for Windows, contains a Windows port of Git. - **Git for Windows** is an alternative requiring minimal runtime support, though a few of the commands need some work. ## Unrelated Files If your project is very large and contains many unrelated files that are constantly being changed, Git may be disadvantaged more than other systems because single files are not tracked. Git tracks changes to the whole project, which is usually beneficial. A solution is to break up your project into pieces, each consisting of related files. Use `git submodule` if you still want to keep everything in a single repository. ## Who’s Editing What? Some version control systems force you to explicitly mark a file in some way before editing. While this is especially annoying when this involves talking to a central server, it does have two benefits: 1. Diffs are quick because only the marked files need be examined. 2. One can discover who else is working on the file by asking the central server who has marked it for editing. With appropriate scripting, you can achieve the same with Git. This requires cooperation from the programmer, who should execute particular scripts when editing a file. ## File History Since Git records project-wide changes, reconstructing the history of a single file requires more work than in version control systems that track individual files. #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 42 Context: The penalty is typically slight, and well worth having as other operations are incredibly efficient. For example, `git checkout` is faster than `cp -a`, and project-wide deltas compress better than collections of file-based deltas. ## Initial Clone Creating a clone is more expensive than checking out code in other version control systems when there is a lengthy history. The initial cost is worth paying in the long run, as most future operations will then be fast and efficient. However, in some situations, it may be preferable to create a shallow clone with the `--depth` option. This is much faster, but the resulting clone has reduced functionality. ## Volatile Projects Git was written to be fast with respect to the size of the changes. Humans make small edits from version to version. A one-liner bugfix here, a new feature there, enumerated comments, and so forth. But if your files are radically different in successive revisions, then on each commit, your history necessarily grows by the size of your whole project. There is nothing any version control system can do about this, but standard Git users will suffer more since normally histories are closed. The reasons why the changes are so great should be examined. Perhaps file formats should be changed. Minor edits should only cause minor changes to at most a few files. Or perhaps a database or backup/archive solution is what is actually being sought, not a version control system. For example, version control may be ill-suited for managing photos periodically taken from a webcam. If the files really must be constantly morphing and they really must be versioned, a possibility is to use Git in a centralized fashion. One can create shallow clones, which check out little or no history of the project. Of course, many Git tools will be unavailable, and fixes must be submitted as patches. This is probably fine as it’s unclear why anyone would want the history of wildly unusable files. Another example is a project depending on firmware, which takes the form of a huge binary file. The history of the firmware is uninteresting to users, and updates compress poorly, so firmware revisions would unnecessarily blow up the size of the repository. In this case, the source code should be stored in a Git repository, and the binary file should be kept separately. To make life easier, one could distribute a script that uses Git to clone the code, and `rsync` or a Git shallow clone for the firmware. #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 43 Context: # Global Counter Some centralized version control systems maintain a positive integer that increases when a new commit is accepted. Git refers to changes by their hash, which is better in many circumstances. But some people like having this integer around. Luckily, it’s easy to write scripts so that with every update, the central Git repository increments an integer, perhaps in a tag, and associates it with the hash of the latest commit. Every clone could maintain such a counter, but this would probably be useless, since only the central repository and its counter matters to everyone. ## Empty Subdirectories Empty subdirectories cannot be tracked. Create dummy files to work around this problem. The current implementation of Git, rather than its design, is to blame for this drawback. With luck, once Git gains more traction, more users will clamour for this feature and it will be implemented. ## Initial Commit A stereotypical computer scientist counts from 0, rather than 1. Unfortunately, with respect to commits, Git does not adhere to this convention. Many commands are unfriendly before the initial commit. Additionally, some corner cases must be handled specially, such as rebasing a branch with a different initial commit. Git would benefit from defining the zero commit: as soon as a repository is constructed, HEAD would be set to the string consisting of 20 zero bytes. This special commit represents an empty tree, with no parent, at some time predating all Git repositories. Then running `git log`, for example, would inform the user that no commits have been made yet, instead of exiting with a fatal error. Similarly for other tools. Every initial commit is implicitly a descendant of this zero commit. However, there are some problem cases unfortunately. If several branches with different initial commits are merged together, then rebasing the result requires substantial manual intervention. ## Interface Quirks For commits A and B, the meaning of the expressions `"A..B"` and `"A...B"` depends on whether the command expects two endpoints or a range. See `git help diff` and `git help rev-parse`. #################### File: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf Page: 44 Context: # Translating This Guide I recommend the following steps for translating this guide, so my scripts can quickly produce HTML and PDF versions, and all translations can live in the same repository. 1. **Clone the source**, then create a directory corresponding to the target language's IETF tag; see the W3C article on internationalization. For example, English is `en` and Japanese is `ja`. In the new directory, translate the text files from the `en` subdirectory. For instance, to translate the guide into Klingon, you might type: ```bash $ git clone git://repo.or.cz/gitmagic.git $ cd gitmagic $ mkdir tlh # "tlh" is the IETF language code for Klingon. $ cd tlh $ cp ../en/intro.txt . $ edit intro.txt # Translate the file. ``` and so on for each text file. 2. **Edit the Makefile** and add the language code to the `TRANSLATIONS` variable. You can now review your work incrementally: ```bash $ make tlh $ firefox book-tlh/index.html ``` 3. **Commit your changes often**, then let me know when they’re ready. GitHub has an interface that facilitates this: fork the "gitmagic" project, push your changes, then ask me to merge. #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 1 Context: # 10. The Network ## 10.1 Introduction Workstations are typically, but not always, connected in a local environment by a network. There exist two basically different views of the architecture of such nets. The more demanding view is that all connected stations constitute a single, unified workspace (also called address-space), in which the individual processors operate. It implies the demand that the "thin" connections between processors are hidden from the users. At worst they might become apparent through slower data access rates between the machines. To hide the difference between access within a computer and access between computers is regarded primarily as a challenge to implementors. The second, more conservative view, assumes that individual workstations are, although connected, essentially autonomous units which exchange data infrequently. Therefore, access of data on partner stations is initiated by explicit transfer commands. Commands handling external access are not part of the basic system, but rather are implemented in modules that might be regarded as applications. In the Oberon System, we adhere to this second view, and in this chapter, we describe the module **Net**, which is an autonomous command module based on the network driver SCC. It can be activated on any station connected in a network, and all of them are treated as equals. Such a set of loosely coupled stations may well operate in networks with moderate transmission rates and therefore with low-cost hardware interfaces and twisted-pair wires. An obvious choice for the unit of transferred data is the file. The central theme of this chapter is therefore file transfer over a network. Some additional facilities offered by a dedicated server station will be the subject of Chapter 11. The commands to be presented here are a few only: `SendFiles`, `ReceiveFiles`, and `SendMsg`. As explained in Chapter 2, Oberon is a single-process system where every command monopolizes the processor until termination. When a command involves communication over a network, (at least) two processors are engaged in the action at the same time. The Oberon paradigm therefore appears to exclude such cooperation; but fortunately it does not, and the solution to the problem is quite simple. Every command is initiated by a user operating on a workstation. For the moment we call it the **master** (of the command under consideration). The addressed station - obviously called the **server** - must be in a state where it recognizes the command in order to engage in its execution. Since the command - called a **request** - arrives in encoded form over the network, an Oberon task represented by a handler procedure must be inserted into the event polling loop of the system. Such a handler must have the general form: ``` IF event present THEN handle event END ``` The guard, in this case, must imply that a request was received from the network. We emphasize that the event is sensed by the server only after the command currently under execution, if any, has terminated. However, data arrive at the receiver immediately after they are sent by the master. Hence, any sizeable delay is inherently inadmissible, and the Oberon metaphor once again appears to fail. It does not fail, however, because the unavoidable, genuine concurrency of sender and receiver action is handled within the driver module which places the data into a buffer. The driver is activated by an interrupt, and its receiver buffer effectively decouples the partners and removes the stringent timing constraints. All this remains completely hidden within the driver module. ## 10.2 The Protocol If more than a single agent participates in the execution of a command, a convention must be established and obeyed. It defines the set of requests, their encoding, and the sequence of data. #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 2 Context: # Protocol Definition In this section, we define a protocol for the exchanges that follow. This convention is used to describe actions initiated by the master and the server. The protocol can be defined using EBNF (Extended Backus-Naur Form), well-known from the syntax specification of programming languages. Items originating from the master will be written in *normal* font, while items from the server appear in *italics*. ## ReceiveFile Request A simple form of the `ReceiveFile` request is defined as follows and will be refined subsequently: ``` ReceiveFile = SND filename (ACK data | NAK). ``` Here, the symbol `SND` represents the encoded request that the server send the file specified by the filename. `ACK` signals that the request is honored and the requested data follows. The `NAK` symbol indicates that the requested file cannot be delivered. The transaction clearly consists of two parts: the request and the reply, one from each partner. This simple-minded scheme fails because of the limitations of the size of each transmitted portion imposed by the network driver. We recall that module SCC restricts the data of each packet to 512 bytes. Evidently, files must be broken up and transmitted as a sequence of packets. The reason for this restriction is transmission reliability. The break-up allows the partner to confirm correct receipt of a packet by returning a short acknowledgment. Each acknowledgment also serves as a request for the next packet. An exception is the last acknowledgment following the last data portion, which is characterized by its length being less than the admitted maximum. The revised protocol is defined as: ``` ReceiveFile = SND filename (DAT data | ACK | NAK). ``` We now recall that each packet is defined as follows: ``` Packet = SND | DAT | ACK | NAK. ``` The symbols `SND`, `DAT`, `ACK`, and `NAK` indicate this packet type. The data portions of `ACK` and `NAK` packets are empty. ### Error Handling The revised protocol fails to cope with transmission errors. Correct transmission is checked by the driver through a cyclic redundancy check (CRC), and an erroneous packet is simply discarded. This implies that a receiver must impose a timing constraint. If an expected packet fails to arrive within a given time period (timeout), the request must be repeated. In our case, a request is implied by an acknowledgment. Hence, the acknowledgment must specify whether the next (normal case) or the previously requested (error case) packet must be sent. The solution is to attach a sequence number to each acknowledgment and to each data packet. These numbers are taken modulo 8, although in principle modulo 2 would suffice. With the addition of a user identification and a password to every request, and of an alternate reply code NRP for "no permission", the protocol reaches its final form: ``` ReceiveFile = SND username password filename (datastream | NAK | NRP). datastream = DAT data ACK | {DAT data ACK...}. ``` The protocol for file transmission from the master to the server is defined similarly: ``` SendFile = REC username password filename (ACK datastream | NAK | NRP). datastream = DAT data ACK | {DAT data ACK...}. ``` The third request listed above, `SendMsg`, does not refer to any file, but merely transmits and displays a short message. It is included here for testing the link between two partners and perhaps for visibly acknowledging a rendered service by the message "done" or "thank you". ``` SendMsg = MSG message ACK. ``` ## 10.3 Station Addressing Every packet must carry a destination address as well as the sender's address. Addresses are station numbers. It would certainly be inconvenient for a user to remember the station number of a desired partner. Instead, the use of symbolic names is preferred. We have become accustomed to use the partner's initials for this purpose. #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 4 Context: # Data Transmission Procedures The hardware discriminates on the basis of the packets' source address, whereas the hardware filter discriminates on the basis of the destination address. If no packet arrives within the allotted time `T`, a type code `-1` is returned, signifying a timeout. ## Procedure ReceiveData The `ReceiveData` checks the sequence numbers of incoming data packets (type 0 - 7). If an incorrect number is detected, an ACK packet with the previous sequence number is returned (type 16 - 23), requesting a retransmission. At most two retries are undertaken. This seems to suffice, considering that also the server does not accept any other requests while being engaged in the transmission of a file. The part corresponding to `ReceiveFiles` within procedure `Serve` is guarded by the condition `head.tpe = SND`. Variable `head` is the recipient of headers whenever a packet is received by `ReceiveHead`. First, the request's parameters are scanned. `Id` and `pw` are ignored. Then the requested file is opened. If it exists, the transmission is handled by `ReceiveData`'s counterpart, procedure `SendData`. The time limit for receiving the next data packet is `T1`, whereas the limit of number of possible (re)transmissions is `T0`. `T1` is roughly `70` multiplied by the maximum data wait until no further retransmission requests can be expected to arrive. The value `T0 (300)` corresponds to `1`; the time for transmission of a packet of maximum length is about `16ms`. ## Procedure SendFiles Procedure `SendFiles` is designed analogously; its counterpart in the server is guarded by the condition `head.tpe = REC`. The server accepts the request only if its state is unprotected (global variable `protected`). Otherwise, the request is negatively acknowledged with an NPR packet. We draw attention to the fact that procedures `SendData` and `ReceiveData` are both used by command procedures as well as by the server. #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 6 Context: ``` checks their validity by examining a table of users. The respective routines and the table are contained in module Core (see Sect. 11.5). ``` **Figure 11.1** Module structure of server systems | | | | | | |---------|---------------|-------------|-----------|----------| | NetServer | LineServer | PrintServer | MailServer | Core | | SCC | RS232 | PrintMaps | | | ## 11.2. Electronic Mail Service The heart of an e-mail service is the set of mailboxes stored on the dedicated, central server. Each registered user owns a mailbox. The evidently necessary operations are the insertion of a message and its retrieval. In contrast to customary letter boxes, however, a retrieved message need not necessarily be removed from the box; its retrieval produces a copy. The box thereby automatically becomes a repository, and messages can be retrieved many times. This scheme calls for an additional command which removes a message from the box. Also, a command is needed for delivering a table of contents, in which presumably each message is represented by an indication of its send time and time of arrival. The mail scheme suggested above results in the following commands: - `Net.Mailbox ServerName`. This command fetches a table of contents of the current user's mailbox from the specified server and displays it in a new viewer. The user's name and password must have been registered previously by the command `System.SetUser`. - `Net.SendMail ServerName`. The text in the marked viewer is sent to the specified server. In order to be accepted, the text must begin with at least one line beginning with "To:" and containing at least one recipient. - `Net.ReceiveMail`. This command is contained in the title bar (menu) of the viewer abandoned when requesting the table of contents. Prior to issuing the command, the message to be read must have been specified by selecting a line in the table of contents in this viewer. This mail system presented here is primarily intended to serve as an exchange for short messages which are typically sent, received, read, and discarded. Mailboxes are not intended to serve as long term archives for a large and ever-growing number of long pieces of text. This restrictiveness of purpose allows to choose a reasonably simple implementation and results in efficient, practically instantaneous access to messages when the server is idle. The Oberon mail server used at ETH also provides communication with external correspondents. It connects to an external mail server which is treated as a source and a sink for messages (almost) like other customers. Additionally, messages sent to that server need to be encoded into a standardized format, and those received need to be decoded accordingly. The parts of module `MailServer` for encoding and decoding are not described in this book. We merely outline the design and implementation took a multiple of the time spent on the last, local message exchange, to which we confine this presentation. From the structures explained in Section 11.1, it follows that three agents are involved in the transfer of messages from the user into a mailbox. Therefore, additions to the server system distribute over three modules. New commands are added to module `Net` (see Section 10.4); these procedures will be listed below. Their counterparts reside in module `NetServer` on the dedicated server. ``` #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 8 Context: # Queue ``` last | v +---+ | n | | 3 | +---+ | v +---+ | | +---+---+---+ | | v v 8 15 | id | jg | hm | rw +---+---+---+ | v NIL ``` **Figure 11.3 Structure of task queue** Every mailbox is represented as a file. This solution has the tremendous advantage that no special administration has to be introduced to handle a reserved partition of disk store for mail purposes. A mailbox file is partitioned into three parts: the block reservation part, the directory part, and the message part. Each part is quickly locatable, because the first two have a fixed length (32 and 31*32 = 992 bytes). The message part is regarded as a sequence of blocks (of 256 bytes), and each message occupies an integral number of adjacent blocks. Corresponding to each block, the block reservation part contains a single bit indicating whether or not the block is occupied by a message. Since the block reservation part is 32 bytes long, the message part contains at most 256 blocks, i.e. 64K bytes. The block length was chosen after an analysis of messages which revealed that the average message is less than 500 bytes long. The directory part consists of an array of 31 elements of type `MailEntry`, a record with the following fields: - `pos` and `len` indicate the index of the message's first block and the message's number of bytes; - `time` and `date` indicate the message's time of insertion, and `originator` indicates the message's source. The entries are linked (field `next`) in chronological order of their arrival, and entry 0 serves as the list's head. It follows that a mailbox contains at most 30 messages. An example of a mailbox table is shown in Figure 11.4. ## MailEntry ``` MAILEntry = RECORD pos: next: INTEGER; len: LONGINT; time: INTEGER; date: ARRAY 20 OF CHAR; END; ``` ## MResTab ``` MResTab = ARRAY 31 OF SET; MailDir = ARRAY 31 OF MailEntry; ``` We are now in a position to implement the handler for requests for message retrieval. It is guarded by the condition `top := SML`. After a valid check, the respective requestor's mailbox file is opened. The mailbox opened is related by the global variable `MF` which acts as a single entry cache. The associated user number is given by the global variable `mailno`. Since typically several requests involving the same mailbox follow, this measure avoids the repeated reopening of the same file. Thereafter, a rider is directly positioned at the respective directory entry for reading the message's length and position in the message part. The rider is repositioned accordingly, and transmission of the message is handled by procedure `SendMail`. #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 12 Context: # User Identification and Password Management Stored passwords are managed through our solution that stores an encoded password. The command `System.SetUser`, which asks for a user identification and a password, immediately encodes the password. The original is stored nowhere; the encoding algorithm is such that it is difficult to construct a corresponding decoder. ## User Identification The mail service requires a third attribute in addition to identification and encoded password: the user's name as it is used for addressing messages. Identification typically consists of the user's initials; for the name, we suggest the full last name of the user and disambiguate cryptic abbreviations. ## Printing Service The printing service makes accounting facility desirable. A fourth field in each user table entry serves as a count for the number of printed pages. As a result, there are four fields: `id`, `name`, `password`, and `count`. The table is not exported but only accessible via procedures. `Core` is a good example of a resource hiding module. The program is listed below, and a few additional comments follow here. ### Procedures - `UserNo(id)` and `UserNum(name)` yield the table index of the identified user; it is called the user number and is used as a short encoding for recipients and senders within the mail server. In other servers, the number is merely used to check a request’s validity. ### User Information User information must certainly survive any interruption of server operation, be it due to software, hardware, or power failure. This requires that a copy of the user information is held on backup storage (disk). The simplest solution would be to use a file for this purpose. However, this would indeed make protection too vulnerable: files can be accessed easily, and we have refrained from introducing a file protection facility. Instead, the backup of the user information is held on a few permanently reserved sectors on the server machine, which are inaccessible to the file system. ## Administrative Procedures Apart from procedures and variables constituting the queuing mechanism for tasks, the procedures exported from module `Core` all belong to the administration, and they can be divided into two categories: 1. **User Management**: - `UserNo`, `UserNum`, `IncPageCount`, `SetPassword`, `GetUserName`, `GetFileName`. 2. **User Inspection**: - `ListUsers`, `GetUsers`, and `Init` for making changes to the table. The client of the latter category is a module `Users` which is needed by the human administrator of the server facility. ## Conclusion The reader may at this point wonder why a more advanced concept of administration has not been chosen, which would allow the human administrator to operate the server remotely. A quick analysis of the consequences of this widely used approach reveals that a substantial amount of additions to our system would be required. The issue of security and protection would become inflated into dimensions that are hardly justified for our local system. The first consequence would be a differentiation among levels of protection. The administrator would become a so-called super-user with extra privileges, such as changing the user table. And so the game of trying to break the protection measures starts to become an interesting challenge. We have resisted the temptation to introduce additional complexity. Instead, we assume that physical access to the server station is reserved to the administrator. Naturally, module `Users` and in particular the symbol file of `Core` do not belong to the public domain. In concluding, we may point out that the impossibility of activating users’ programs on the server station significantly reduces the possibilities for inflicting damage from the exterior. #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 13 Context: # 12 The Compiler ## 12.1 Introduction The compiler is the primary tool of the system builder. It therefore plays a prominent role in the Oberon System, although it is not part of the basic system. Instead, it constitutes a tool module - an application - with a single command: `Compile`. It translates program texts into machine code. Therefore, it is a program inherently machine-dependent; it acts as the interface between source language and target computer. In order to understand the process of compilation, the reader needs to be familiar with the source language Oberon defined in Appendix 1, and with the target computer RISC, defined in Appendix 2. The language is defined as an infinite set of sequences of symbols taken from the language's vocabulary. It is described by a set of equations called syntax. Each equation defines a syntactic construct, or more precisely, the set of sequences of symbols belonging to that construct. It specifies how that construct is composed of other syntactic constructs. The meaning of programs is defined in terms of semantic rules governing each such construct. Compilation of a program text proceeds by analyzing the text and thereby decomposing it recursively into its constructs according to the syntax. When a construct is identified, code is generated according to the semantic rule associated with the construct. The components of the identified construct supply parameters for the generated code. It follows that we distinguish between two kinds of actions: analyzing steps and code generating steps. In a rough approximation we may say that the former are source language dependent and target computer dependent, whereas the latter are source language independent and target computer dependent. Although reality is somewhat more complex, the module structure of this compiler clearly reflects this division. The main module of the compiler is ORP (for Oberon to RISC Parser). It is primarily dedicated to syntactic analysis, parsing. Upon recognition of a syntactic construct, an appropriate procedure is called to the code generator module ORG (for Oberon to RISC Generator). Apart from parsing, ORP checks for type consistency of operands, and it computes the attributes of objects identified in declarations. Whereas ORP mirrors the source language and is independent of a target computer, ORG reflects the target computer, but is independent of the source language. Oberon program texts are regarded as sequences of symbols rather than sequences of characters. Symbols themselves, however, are sequences of characters. We refrain from explaining the reasons for this distinction, but mention that apart from special characters and pairs such as `.`, `,`, as well as identifiers, numbers, and strings are classified as symbols. Furthermore, certain capital letter sequences are symbols, such as `IF`, `END`, etc. Each time the syntax analyzer (parser) proceeds to read the next symbol, it does this by calling procedure `Get`, which constitutes the so-called scanner residing in module ORS (for Oberon to RISC Scanner). It reads from the source text as many characters as are needed to recognize the next symbol. In passing, we note that the scanner also reflects the definition of symbols in terms of characters, whereas the parser is based on the notion of symbols only. The scanner implements the abstraction of symbols. The recognition of symbols within a character sequence is called **lexical analysis**. Ideally, the recognition of any syntactic construct, say `A`, consisting of subconstructs, say `B1`, `B2`, ..., `Bn`, leads to the generation of code that depends only on (1) the semantic rules associated with `A`, and (2) on attributes of `B1`, `B2`, ..., `Bn`. If this condition is satisfied, the construct is said to be context-free, and if all constructs of a language are context-free, then the language is context-free. Syntax and semantics of Oberon adhere to this rule, although with a significant exception. #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 15 Context: # Variable Allocation in RISC Processors In RISC processors, variable allocation uses a straightforward scheme of sequential allocation of consecutively declared variables. An address is a pair consisting of a base address (in a register) and an offset. Global variables are allocated in the module's data section and the respective base address register is SB (Static Base, see Chapter 6). Local variables are allocated in a procedure activation record on the stack; the respective base register is SP (Stack Pointer). Offsets are positive integers. The amount of storage needed for a variable (called its *size*) is determined by the variable's type. The sizes of basic types are prescribed by the target computer's data representation. The following holds for the RISC processor: | Type | No. of bytes | |--------------------------|--------------| | BYTE, CHAR, BOOLEAN | 1 | | INTEGER, REAL, SET, POINTER, PROCEDURE | 4 | The size of an array is the size of the element type multiplied by the number of elements. The size of a record is the sum of the sizes of its fields. A complication arises due to so-called alignment. By alignment is meant the adjustment of an address to a multiple of the variable's size. Alignment is performed for variable addresses as well as for record field offsets. The motivation for alignment is the avoidance of double memory references for variables being "distributed" over two adjacent words. Proper alignment enhances processing speed quite significantly. Variable allocation using alignment is shown by the example in Fig. 12.2. ## Example of Variable Allocation ``` VAR b0: BYTE; int0: INTEGER; b1: BYTE; int1: INTEGER; ``` ``` b0 int0 | b1 | int1 | -------------- int0 b1 int1 ``` ### Figure 12.2: Alignment of variables We note in passing that a reordering of the four variables lessens the number of unused bytes, as shown in Fig. 12.3. ``` VAR int0, int1: INTEGER; b0, b1: BYTE; ``` ``` int0 int1 b1 | b0 ``` ### Figure 12.3: Improved order of variables Memory instructions compute the address as the sum of a register (base) and an offset constant. Local variables use the *stack pointer* SP (R14) as base, global variables the static base SB (R13). Every module has its own SB value, and therefore access to global (and imported) variables requires two instructions, one for fetching the base value, and one for loading or storing data. If the compiler can determine whether the correct base value has already been loaded into the SB register, the former instruction is omitted. The first 7 sample patterns contain global variables only, and their base SB is assumed to hold the appropriate value. Parameters of branch instructions denote jump distances from the instruction's own location (PC-relative). #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 17 Context: # Pattern3: Indexed Variables References to elements of arrays make use of the possibility to add an index value to an offset. The index must be present in a register and multiplied by the size of the array elements. (For integers with size 4 this is done by a shift of 2 bits). Then the index is checked whether it lies within the bounds specified in the array's declaration. This is achieved by a comparison, actually a subtraction, and a subsequent branch instruction causing a trap, if the index is either negative or beyond the upper bound. If the reference is to an element of a multi-dimensional array (matrix), its address computation involves several multiplications and additions. The address of an element A[i1, ..., ik] of a k-dimensional array A with lengths n1, ..., nk is: ``` A(i) + ((...(((i1 * n2) + i2) * n3 + ...) * n_k) + i_k) * n1) + n0 ``` Note that for index checks `CMP` is written instead of `SUB` to mark that the subtraction is merely a comparison, that the result remains unused and only the condition flag registers hold the result. ## MODULE Pattern3: ```assembly VAR i, j, k: INTEGER; 0, 4, 8, 12 a: ARRAY 10 OF INTEGER; 16 x: ARRAY 10, 10 OF INTEGER; 56 y: ARRAY 10, 10 OF INTEGER; 456 BEGIN k := a[j]; LDR R0 S8 CMP R1 10 BLH R12 LSL R0 2 ADD R0 S8 R0 LDR R0 R0 16 STR R0 S8 n := a[5]; LDR R0 S8 STR R0 S8 12 x[i, j] := 2; LDR R0 S8 CMP R1 10 BLH R12 MUL R0 R0 40 ADD R0 R0 S8 CMP R2 R1 10 BLH R12 LDR R0 S8 4 y[i, j] := k - 3; LDR R0 S8 CMP R1 10 BLH R12 MUL R1 R0 400 ADD R0 R0 S8 LDR R1 S8 4 CMP R2 R1 10 END Pattern3. ``` #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 19 Context: ``` # MODULE Pattern5; VAR INTEGER: s; SET: 0, 4; BEGIN IF n = 0 THEN LDR R0 S8 ... CMP R0 R0 BNE ... INC(n) LDR R0 S8 ... ADD R0 R0 1 STR R0 S0 END; IF (n >= 0) AND (n < 100) THEN LDR R8 S8 ... LDR R0 S0 (n) CMP R0 R0 BLT 6 LDR R0 S8 CMP R0 R0 100 BGE 3 DEC(n) LDR R0 S8 ... SUB R0 R0 1 STR R0 0 END; IF (ODD(n)) OR (n IN s) THEN LDR S8 R0 ... LDR R0 S0 (n) AND R0 R0 BNE 5 LDR R0 S8 4 (s) LDR R1 S8 0 ADD R1 R1 1 ROL R0 R1 BPL 2 STR R0 S0 n = -1000 MOV R0 R0 -1000 STR R0 S0 END; IF n < 0 THEN LDR R0 S8 ... LDR R0 S0 CMP R0 R0 BGE 3 MOV R0 R0 {} STR R0 S8 4 B 17 END; ELSIF n < 10 THEN LDR R0 S8 ... LDR R0 S0 CMP R0 R0 10 BGE 3 MOV R0 R1 1 STR R0 S8 4 B 18 END; ELSIF n < 100 THEN LDR R0 S8 ... LDR R0 S0 CMP R0 R0 100 BGE 3 MOV R0 R0 2 STR R0 S8 4 B 19 ELSE MOV R0 R4 ... LDR R0 S8 ... STR R0 S8 4 END; END Pattern5. # Pattern 6: While and repeat statements. ``` #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 28 Context: ``` ROR R0, R1 STR R0, SB 12 y b := ODD(n); LDR R0, SB 4 n AND R0, R1 BEQ 2 MOV R0, R1 B 1 MOV R0, 0 STS R0, SB 16 b n := ORD(ch); LDB R0, SB 17 ch STR R0, SB 4 n n := FLOOR(x); LDR R0, SB 4 x MOV R1, R0, 480H FAD R0, R1 STR R0, SB 1 floor STR R0, SB 4 n y := FLT(m); LDR R0, SB 0 m MOV R1, R0, 480H FAD R0, R1 float STR R0, SB 12 y n := LSL(m, 3); LSL R0, SB 4 n STR R0, SB 4 n n := ASR(m, 8); LDR R0, SB 0 8 ASR R0, SB 4 STR R0, SB 4 n m := ROR(m, n); LDR R1, SB 4 LDR R0, R0, R1 ROR R0, R1 STR R0, SB 0 END Pattern17 # 12.3. Internal data structures and module interfaces ## 12.3.1. Data structures In Section 12.1 it was explained that declarations inherently constitute context-dependence of the translation process. Although parsing still proceeds on the basis of a context-free syntax and relies on contextual information only in a few isolated instances, information provided by declarations affects the generated code significantly. During the processing of declarations, their information is transferred into the “symbol table”, a data structure of considerable complexity, from where it is retrieved for the generation of code. This dynamic data structure is defined in module ORB in terms of two record types called `Object` and `Struct`. These types prevail over all modules with the exception of the scanner. They are therefore explained before further details of the compiler are discussed (see module ORB below). For each declared identifier an instance of type `Object` is generated. The record holds the identifier and the properties associated with the identifier given in its declaration. Since Oberon is a statically typed language, every object has a type. It is represented in the record by its type field, which is a pointer to a record of type `Struct`. Since many objects may be of the same type, it is appropriate to record the type’s attributes only once and to refer to them via a pointer. The properties of type `Struct` will be discussed below. The kind of object which a table entry represents is indicated by the field class. Its values are denoted by declared integer constants: `Var` indicates that the entry describes a variable, `Con` a constant, `Fct` a record field, `Par` a VAR-parameter, and `Proc` a procedure. Different kinds of entries carry different attributes. A variable or a parameter carries an address, a constant has a value, a record field has an offset, and a procedure has an entry address, a list of parameters, and a result type. For each class the introduction of an extended record type would seem advisable. This was not done, however, for three reasons. First, the compiler was first formulated in (a subset of) 28 ``` #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 33 Context: ``` # PROCEDURE Init; # PROCEDURE Close; # PROCEDURE NewObj (VAR obj: Object; id: ORS.Ident; class: INTEGER); # PROCEDURE ThisObj(): Object; # PROCEDURE ThinObject (mod: Object): Object; # PROCEDURE Finished (rec: Type): Object; # PROCEDURE OpenScope; # PROCEDURE CloseScope; # PROCEDURE Import (VAR mod: modid: ORS.Ident); # PROCEDURE Export (VAR mod: ORS.Ident); # END ORG. VAR newSF: BOOLEAN; VAR key: INTEGER; Module ORG contains the procedures for code generation. The names of these procedures indicate the respective constructs for which code is to be produced. Note that an individual code generator procedure is provided for every standard, predefined procedure. This is necessary because they generate in-line code. ## DEFINITON ORG; CONST WordSize = 4; TYPE Item = RECORD mode: INTEGER; typ: ORB.Type; a, b: INTEGER; rdb: BOOLEAN; (* "read only" *) END; VAR x: INTEGER; ### PROCEDURES - PROCEDURE MakeConstItem(VAR x: Item; typ: ORB.Type; var: INTEGER); - PROCEDURE MakeRealItem(VAR x: Item; val: REAL); - PROCEDURE MakeStringItem(VAR x: Item; len: INTEGER); - PROCEDURE MakeWrite(VAR x: Item; var: ORB.Object; curlev: INTEGER); - PROCEDURE Field(VAR x: Item; y: Object); (* x <- x.y *) - PROCEDURE Index(VAR x: VAR; y: Item); (* x <- x[y] *) - PROCEDURE Ref(VAR x: Item); - PROCEDURE BufPut(VAR x: Item; VAR y: INTEGER); - PROCEDURE TypeTest(VAR x: Item; t: ORB.Type; vararg: BOOLEAN); - PROCEDURE Not(VAR x: Item); (* x <- ~x, Boolean operators *) - PROCEDURE And1(VAR x: Item); (* x <- x && x *) - PROCEDURE And(VAR x: Item); (* x <- x && x OR *) - PROCEDURE Or1(VAR x: Item); (* x <- x OR x *) - PROCEDURE Or2(VAR x: VAR; y: Item); - PROCEDURE Neg(VAR x: Item); (* x <- -x, arithmetic operators *) - PROCEDURE AddOp(VAR x: Item); (* x <- x + y *) - PROCEDURE SubOp(VAR x: VAR; y: Item); (* x <- x - y *) - PROCEDURE MulOp(VAR x: Item; y: Item); (* x <- x * y *) - PROCEDURE DivOp(VAR x: INTEGER; VAR y: Item); (* x <- x / y *) - PROCEDURE RealOp(VAR x: INTEGER; VAR y: Item); (* x <- x op y *) - PROCEDURE Singleton(VAR x: Item); (* x <- x, set operators *) - PROCEDURE Set(VAR x: VAR; y: Item); (* x <- x ∪ y *) - PROCEDURE Insert(VAR x: Item; y: Item); (* x <- x + y *) - PROCEDURE SetOp(VAR op: INTEGER; VAR x: VAR; y: Item); (* x <- x op y *) - PROCEDURE IntRelation(VAR op: INTEGER; VAR x: Item); (* x <- x op y *) - PROCEDURE RealRelation(op: INTEGER; VAR y: Item); (* x <- x op y *) - PROCEDURE StringRelation(VAR x: VAR; y: Item); (* x <- x y *) - PROCEDURE StrToChar(VAR x: Item); (* "assignments" *) - PROCEDURE Store(VAR x: VAR; y: Item); (* x <- y *) - PROCEDURE StoreStr(VAR x: Item; y: Item); (* x <- y *) - PROCEDURE CopyString(VAR x: VAR; y: Item); (* from x to y *) ``` #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 35 Context: # ORP Compiler ## Overview ### ORP.Compile @ The most recent selection identifies the beginning of the source text. ### ORP.Compile ^ The most recent selection identifies the name of the source file. ### ORP.Compile f0 | f1 | ... These are the names of source files. File names and the characters `@` and `^` may be followed by an option specification `/s`. Option `/s` enables the compiler to overwrite an existing symbol file, thereby invalidating clients. ## Parser Design The parser is designed according to the proven method of top-down, recursive descent parsing with a look-ahead of a single symbol. The last symbol read is represented by the global variable `sym`. Syntactic entities are mirrored by procedures of the same name. Their goal is to recognize the specified construct in the source text. The start symbol and corresponding procedure is `Module`. The principal parser procedures are shown in Fig. 12.6, which also exhibits their calling hierarchy. Loops in the diagram indicate recursion in the syntactic definition. ### Figure 12.6: Parser Procedure Hierarchy ``` Module ___________ | | Declarations StatSeq | | Type ProcDecl _______ _______ | | | | RecType ArrayType FPSection | | | FormalType ParameterList ________ | | ParamList SimpleExp ____________ | | term expression | factor | element ``` ## Rule Violations The rule of parsing strictly based on a single-symbol look-ahead and without reference to context is violated in three places. The prominent violation occurs in statements. If the first symbol of a statement is an identifier, the decision of whether an assignment or a procedure call is to be recognized is based on contextual information, namely the class of the identified object. The second violation occurs in `qualified`: if the identifier `x` preceding a period denotes a module, it is recognized together with the subsequent identifier as a qualified identifier. Otherwise, it is supposedly denotes a record variable. The third violation is made in procedure `selector`: if an identifier is followed by a left parenthesis, the decision of whether a procedure call or a type guard is to be recognized is again made on the basis of contextual information, namely the mode of the identified object. ## Error Discovery A fairly large part of the program is devoted to the discovery of errors. Not only should they be properly diagnosed, but a much more difficult requirement is that the parsing process should continue on the basis of a good guess about the structure that the text should most likely have. The parsing process must continue with some assumption and possibly after skipping a short piece of the object. #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 39 Context: # 12.6.2 Symbol files A search of an identifier proceeds first through the scope list, and for each header its list of object records is scanned. This mirrors the scope rule of the language and guarantees that if several entities carry the same identifier, the most local one is selected. The linear list of objects represents the simplest implementation by far. A tree structure would in many cases be more efficient for searching and would therefore seem more recommendable. Experiments have shown, however, that the gain in speed is marginal. The reason is that the lists are typically quite short. The superiority of a tree structure becomes manifest only when a large number of global objects is declared. We emphasize that when a tree structure is used for each scope, the linear lists must still be present, because the order of declarations is sometimes relevant in interpretation, e.g., in parameter lists. Not only procedures, but also record types establish their own local scope. The list of record fields is anchored in the type record's field des, and it is searched by procedure `thisField`. If a record type `R1` is an extension of `R0`, then `R1`'s field list contains only the fields of the extension proper. The base type `R0` is referenced by the `BaseTyp` field of `R1`. Hence, a search for a field may have to proceed through the field lists of an entire sequence of record base types. The major part of module `ORB` is devoted to input and output of symbol files. A symbol file is a linearized form of an excerpt of the symbol table containing descriptions of all exported (marked) objects. All exports are declared in the global scope. Procedure `Export` traverses the list of global objects and outputs them to the symbol file. The structure of a symbol file is defined by the syntax specified below. The following terminal symbols are class and form specifiers or reference numbers for basic types with fixed values: Classes: - `Cons`: `C` = 1, `Var` = 2, `Par` = 3, `Id` = 4, `Typ` = 5 Forms: - `Byte` = 1, `Bool` = 2, `Char` = 3, `Int` = 4, `Lint` = 5, `Set` = 6 - `Pointer` = 7, `NotBy` = 9, `ProcTyp` = 10, `Array` = 12, `Record` = 13 ```markdown Symbol = null key name versionkey (object) object = (CON name type {value} [ | TYPE name type {fix} 0 | VAR name type expn]) type = ref (PTR type | ARR type len | REC type {field} [ | PRO type {param}]) ``` #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 44 Context: # 12.7.2 Relations RISC does not feature any compare instruction. Instead, subtraction is used, because an implicit comparison with 0 is performed along with any arithmetic (or load) instruction. Instead of \( x < y \) we use \( x - y \). This is possible because, in addition to the computed difference deposited in a register, also the result of the comparison is deposited in the condition flags \( N \) (difference negative) and \( Z \) (difference zero). Relations therefore yield a result item \( x \) with mode `Cond.x < y (rel(jumps))` identifies the relation. Branch instructions (jumps) are executed conditionally depending on these flags. The value \( x.r \) is then used when generating branch instructions. For example, the relation \( x < y \) is translated simply into: ``` LDR R0, SP, x LDR R1, SP, y CMP R0, R0, R1 ``` and the resulting item mode is `x.mode = Cond, x.r = "less"`. (The mnemonic CMP is synonymous with SUB). More about relations and Boolean expressions will be explained in Section 12.7.6. ## 12.7.3 Set operations The type `SET` represents sets of small integers in the range from 0 to 31. Bit \( i \) signals that \( i \) is an element of the set. This is a convenient representation because the logical instructions directly mirror the set operations: AND implements set intersection, OR set union, and XOR the symmetric set difference. This representation also allows a simple and efficient implementation of membership tests. The instructions for the expression \( \text{m IN s} \) is generated by procedure `In`. Assuming the value in register R0, and the set \( s \) in R1, we obtain: ``` ADD R0, R0, 1 ROR R1, R1, R0 // rotate s by i+1 position, the relevant bit moving to the sign bit ``` The resulting item mode is `Cond.x = r - "minus"`. Of some interest are the procedures for generating sets, i.e. for processing \( \{m\}, \{m .. n\} \), and \( \{m, n\} \), where \( m, n \) are integer expressions. We start with \( \{m\} \). It is generated by procedure `Singleton` using a shift instruction. Assuming \( m \) in R0, the resulting code is: ``` MOV R1, 0, 1 LSL R0, R1, R0 // shift 1 by m bits positions to the left ``` Somewhat more sophisticated is the generation of \( \{m .. n\} \) by procedure `Set`. Assuming \( m \) in R0, and \( n \) in R1, the resulting code is: ``` MOV R0, 0, 2 LSL R1, R2, R1 // shift -2 by n bits positions to the left MOV R0, 2, -1 LSL R0, R2, R0 // shift -1 by m bits positions to the left XOR R0, R0, R1 ``` The set \( \{m, n\} \) is generated as the union of \( \{m\} \) and \( \{n\} \). If any of the element values is a constant, several possibilities of code improvement are possible. For details, the reader is referred to the source code of ORG. ## 12.7.4 Assignments #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 45 Context: ``` Statements have an effect, but no result like expressions. Statements are executed, not evaluated. Assignments alter the value of variables through store instructions. The computation of the address of the affected variable follows the same scheme as for loading. The value to be assigned must be in a register. Assignments of arrays (and records) are an exceptional case in so far as they are performed not by a single store instruction, but by a repetition. Consider `y = x`, where `x` and `y` are both arrays of `n` integers. Assuming that the address of `y` is in register `R0`, that of `x` in `R1`, and the value in `R2`. Then the resulting code is: ``` LDR R3, R1, 0 ; source ADD R1, R1, 4 ; increment index STR R3, R0, 0 ; destination ADD R0, R0, 4 ; increment destination SUB R2, R2, 1 ; counter BNE L2 ; branch if not equal ``` ## 12.7.5 Conditional and repetitive statements These statements are implemented using branch instructions (jumps) as shown in Section 12.2, Patterns 5 - 7. In all repetitive statements, backward jumps occur. Here, at the point of return the value of the global variable `ORG.pc` is saved in a local (`l`) variable of the involved parsing procedure. It is retrieved when the backward jump is emitted. We note that branch instructions use a displacement rather than an absolute destination address. It is the difference between the branch instruction and the destination of the jump. A difficulty, however, arises in the case of forward jumps, a difficulty inherent in all single-pass compilers: When the branch is issued, its destination is still unknown. It follows that the branch displacement must be later resolved when it becomes known, when the destination is reached. This is called a `fixup`. Here the method of fixup lists is used. The place of the instruction with still unknown destination is held in a variable `L` for the respective parsing procedure. If several branches have the same destination, `L` is the heading of a list of the instructions to be fixed up, with its links placed in the instructions themselves in the place of the eventual jump displacement. This shows how to fix a statement by an excerpt of `ORP.StaSequence` with local variable `L0`: ``` ELSEIF sym = ORS.IF THEN ORS.Get(sym); expression(x); ORG.FJump(x); StatSequence: L0 := 0; WHILE sym = ORS.ELSE DO ORS.Get(sym); ORG.FJump(L0); ORG.Fixup(x); expression(x); END; IF sym = ORS.Else THEN ORS.Get(sym); ORG.FJump(L0); ORG.Fixup(x); StatSequence ELSE ORG.Fixup(x); END; ORG.FixLink(L0); ``` ### where in module ORG: ``` PROCEDURE FJump(VAR x: Item); (* conditional forward jump *) BEGIN IF x.mode <> Cond THEN loadCond(x) END; PUJ3(BG, negated(x), x.a); FLinkLink(x); x.a := pc-1; END FJump; PROCEDURE JFJump(VAR L: LONGINT); (* unconditional forward jump *) BEGIN PUJ3(BC, 7); L := L - 1; END FJump; PROCEDURE fix(at: VAR LONGINT); BEGIN code[at] := code[at] DIV C24 * C24 + (with MOD C24); END fix; ``` ``` #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 47 Context: # 12.7 Stack frames Scheme and layout determine the code sequences for call, entry, and exit of procedures. Here is an example of a procedure P with 2 parameters: **Call:** ``` LDR R0, param0 LDR R1, param1 BL P ``` **Prolog:** ``` SUB SP, SP, size // decrement SP STR LNK, SP, 0 // push return adr STR R0, SP, 4 // push parameter 0 STR R1, SP, 8 // push parameter 1 .... ``` **Epilog:** ``` LDR LNK, SP, 0 // pop return adr ADD SP, SP, size // increment SP BR LNK ``` When the call instruction is executed, parameters reside in registers, starting with R0. For function procedures, the result is passed in register R0. This scheme is very efficient; storing the parameters occurs only in a single place, namely at procedure entry, and not before each call. However, it has severe consequences for the entire register allocation strategy. Throughout the compiler, registers **must** be allocated in strict stack fashion. Furthermore, parameter allocation must start with R0. This is a distinct drawback for function calls. If registers are occupied by other values loaded prior to the call, they must be cleared, i.e., the parameters must be saved and reloaded after return. This is rather cumbersome (see procedures ORG.SaveRegisters and ORG.RestoreRegisters). | F(x) | no register saving | |--------------------|-------------------| | F(x) | | | (x+1) + F(x) | register saving necessary | ## 12.8 Type extension Static typing is an important principle in programming languages. It implies that every constant, variable, or function is of a certain data type, and that this type can be derived by reading the program text without executing it. It is the key principle to introduce important redundancy in languages in such a form that a compiler can detect inconsistencies. It is therefore the key element for reducing the number of errors in programs. However, it also acts as a restriction. It is, for example, impossible to construct data structures (arrays, trees) with different types of elements. In order to relax the rule of strictly static typing, the notion of **type extension** was introduced in Oberon. It makes it possible to construct. #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 48 Context: TYPE R0 = RECORD u: INTEGER END; R1 = RECORD (R0) u: INTEGER END; We say that R1 is an extension of R0. R0 has the fields u and v, R1 has u, v, and w. The concept becomes useful in combination with pointers. Let ``` TYPE P = POINTER TO R0; P1 = POINTER TO R1; VAR p0: P0; p1: P1; ``` Now it is possible to assign p1 to p0 (because a P1 is always also a P0), but not p0 to p1, because a P0 need not be a P1. This has the simple consequence that a variable of type P0 may well point to an extension of R0. Therefore, data structures can be declared with a base type, P0, as common element type, but in fact they can individually differ; they can be any extension of the base type. Obviously, it must be possible to determine the actual, current type of an element even if the base type is statically fixed. This is possible through a type test, syntactically a Boolean factor: ``` p0 IS P1 ``` (short for `p0 IS R1`) Furthermore, we introduce the type guard. In the present example, the designator `p0.v` is illegal, because there is no field `v` in a record of type P0, even if the current value of p0 is a R1. As this case occurs frequently, we introduce the short notation `p0(P1,p)`, implying a test `p0 IS P1` and an abort if the test is not met. It is important to mention that this technique also applies to formal variable parameters of record type, as they also represent a pointer to the actual parameter. Its type may be any extension of the type specified for the formal parameter in the procedure heading. How are type test and type guard efficiently implemented? Our first observation is that they must consist of a single comparison only, similar to index checks. This in turn implies that types must be identified by a single word. The solution lies in using the unique address of the type descriptor of the (record) type. Which data must this descriptor hold? Essentially, type descriptors (TD) must identify the base types of a given type. Consider the following hierarchy: ``` TYPE T = RECORD ... END; T0 = RECORD (T) ... END; // extension level 1 T1 = RECORD (T) ... END; // extension level 1 T00 = RECORD (T0) ... END; // extension level 2 T10 = RECORD (T1) ... END; // extension level 2 T11 = RECORD (T1) ... END; // extension level 2 ``` #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 49 Context: # Type Hierarchy In the symbol table, the field base refers to the ancestor of a given record type. Thus base of the type representing T11 points to T1, etc. Run-time checks, however, must be last, and hence cannot proceed through chains of pointers. Instead, each TD contains an array with references to the ancestor TDs (including itself). For the example above, the TDs are as follows: - `TD(T)` = `[]` - `TD(TI)` = `[T, TI]` - `TD(T00)` = `[T, T00]` - `TD(T01)` = `[T, T01]` - `TD(T10)` = `[T, T10]` - `TD(T11)` = `[T, T11]` Evidently, the first element can be omitted, as it always refers to the common base of the type hierarchy. The last element always points to the TD's owner. TDs are allocated in the data area, the area for variables. ## References to TDs References to TDs are called type tags. They are required in two cases. The first is for records referenced by pointers. Such dynamically allocated records carry an additional, hidden field holding their type tag. (A second additional word is reserved for use by the garbage collector. The offset of the tag field is therefore -8.) The second case is that of record-typed VAR-parameters. In this case, the type tag is explicitly passed along with the address of the actual parameter. Such parameters therefore require two words/registers. A type test consists of a test for equality of two type tags. In PS, the first tag is that of the n-th entry of the TD of `p`, where `n` is the extension level of `T`. The second tag is that of type `T`. This is shown in Pattern 1 in Section 12.2 (see also Fig. 12.4). The test then is as follows: - `p.tag[tl] = addr(T)`, where `l` is the extension level of `T`. When declaring a record type, it is not known how many extensions, or how many levels will be built on this type. Therefore, TDs should actually be infinite arrays. We decided to restrict them to 3 levels only. The first entry, which is never used for checking, is replaced by the size of the record. ## 12.7.9 Import and Export, Global Variables Addresses of imported objects are not available to the compiler. Their computation must be left to the module loader (see Chapter 6). Similar to handling addresses of imported modules, the compiler puts the necessary information in place of the actual addresses into the instruction itself. In the case of procedure calls, this is quite feasible, because the BL instruction features an offset of 24 bits. The information consists of the module number and the export number of the imported object. In addition, there is a link to the previous instruction referring to an imported procedure. The origin of the first imported circular jump is rooted in the compiler variable `fork`, and the 24 bits in each BL instruction 4 bits are used for the module number, 8 bits for the object's export number, and 12 for the link. The loader need only scan this list to fix up the addresses (jump offsets). Matters are more complex in the case of data. Object records in the symbol table have a field lev. It indicates the nesting level of variables local to procedures. It is also used for the module number in the case of variables of imported modules. Note that when importing, objects designating modules are inserted in the symbol table, and the list of their own objects are attached in the field `disc`. In this #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 50 Context: # 12.7.10 Traps This compiler provides an extensive system of safeguards by providing run-time checks (aborts) in several cases: | trap number | trap cause | |-------------|----------------------------------| | 1 | array index out of range | | 2 | type guard failure | | 3 | array or string copy overflow | | 4 | access via NIL pointer | | 5 | illegal procedure call | | 6 | integer division by zero | | 7 | assertion violated | These checks are implemented very efficiently in order not to downgrade a program's performance. Involved is typically a simple compare instruction, plus a conditional branch (BLR MT). It is assumed that any entry of the module table contains not a base address (module numbers start with 1), but a branch instruction to an appropriate trap routine. The trap number is encoded in bits 47:0 of the branch instruction. The predefined procedure `Assert` generates a conditional trap with trap number 7. For example, the statement `Assert(m = n)` generates: ``` LDR R0, m LDR R1, n CMP R0, R1 BLR R1, 7CH ; branch and link if unequal through R12 (MT), trap number 7 ``` Procedure `New`, representing the operator `NEW`, has been implemented with the aid of the trap mechanism. (This is in order to omit any reference to module `Kernel`, which contains the allocation procedure `New`). The generated code for the statement `NEW(p)` is: ``` ADD R0, R0, SP ; address of p ADD R1, SB, tag ; type tag BLR R1, 7CH ; branch and link unconditionally through R12 (MT), trap number 0 ``` #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 51 Context: # 13 A graphics editor ## 13.1 History and goal The origin of graphics systems as they are in use at this time was intimately tied to the advent of the high-resolution bit-mapped display and of the mouse as pointing device. The author's first contact with such equipment dates back to 1976. The Alto computer at the Xerox Palo Alto Research Center is justly termed the first workstation featuring those characteristics. The designer of its first graphics package was Ch. Thacker who perceived the usefulness of the high-resolution screen for drawing and processing schematics of electronic circuits. This system was cleverly tailored to the needs encountered in this activity, and it was remarkable in its compactness and effectiveness due to the lack of unnecessary facilities. Indeed, its acronym was SIL, for Simple Illustrator. After careful study of the used techniques, the author designed a variant, programmed in Modula-2 (instead of BCPL) for the PDP-11 Computer, thereby ordering and exhibiting the involved data structures more explicitly. In intervals of about two years, that system was revised and grew gradually into the present Draw system. The general goal remained a simple line drawing system: emphasis was placed on a clear structure and increase of flexibility through generalization of existing rather than indiscriminate addition of new features. In the history of this evolution, three major transitions can be observed. The first was the move from a single “window”, the screen, to multiple windows showing different excerpts of the same graphic. This step was performed on the Lilith computer which resembled the Alto in many ways. The second major transition was the application of the object-oriented style of programming, which allowed the addition of new element types to the basic system, making it extensible. The third step concerned the proper integration of the Draw system with Oberon’s text system. The last two steps were performed using Oberon and the Ceres computer. We refrain from exhibiting this evolution and merely present the outcome, although the history might be an interesting reflection of the evolution of programming techniques in general, containing many useful lessons. We stress the fact, however, that the present system rests on a long history of development, during which many features and techniques were introduced and later discarded or revised. The size of the system's description is a poor measure of the effort that went into its construction; deletion of program text sometimes marks bigger progress than addition. The goal of the original SIL program was to support the design of electronic circuit diagrams. Primarily, SIL was a line drawing system. This implies that the drawings remain uninterrupted. However, in a properly integrated system, the addition of modules containing operators that interpret the drawings is a reasonably straightforward proposition. In fact, the Oberon system is ideally suited for such steps, particularly due to its command facility. At first, we shall ignore features specifically tailored to circuit design. The primary one is a macro facility to be discussed in a later chapter. The basic system consists of the modules Draw, GraphicFrames, and Graphics. These modules contain the facilities to generate and handle horizontal and vertical lines, text captions, and macros. Additional modules serve to introduce other elements, such as rectangles and circles, and the system is extensible. Further modules may be introduced to handle further types of elements. ## 13.2 A brief guide to Oberon's line drawing system In order to provide the necessary background for the subsequent description of the Draw system's implementation, a brief overview is provided in the style of a user's guide. It summarizes the facilities offered by the system and gives an impression of its versatility. The system called Draw serves to prepare line drawings. They contain lines, text captions, and other items, and are displayed in graphic viewers (more precisely: in menu viewers' graphic frames). #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 52 Context: # Graphic Viewer Commands The graphic viewer shows an excerpt of the drawing plane, and several viewers may show different parts of a drawing. The most frequently used commands are built-in as mouse clicks and combinations of clicks. Additional commands are selectable from texts, either in viewer menus (title bars) or in the text called **Draw Tool**. Fig. 13.1 shows the display with two graphic viewers at the left and the draw tool text at the right. The mouse buttons have the following principal functions whenever the cursor lies in a graphic frame: - **left:** draw / set caret - **middle:** move / copy - **right:** select ## 13.2.1 Basic Commands The command **Draw.Open** opens a new viewer and displays the graph with the name given as a parameter. We suggest that file names use the extension `.graph`. ### Drawing a Line In order to draw a horizontal or vertical line from P0 to P1, the left key is pressed with the cursor at P0 and, while the key is held, the mouse and cursor is moved to P1. Then the key is released. If P0 and P1 differ in both their x and y coordinates, then the end point is adjusted so that the line is either horizontal or vertical. ### Writing a Caption First, the cursor is positioned where the caption is to appear. Then the left key is clicked, causing a crosshair to appear. It is called the caret. Then the text is typed. Only single lines of text are accepted. The DEL key may be used to retract characters (backspace). ### Selecting Elements Most commands require the specification of operands, and many implicitly assume the previously selected elements - the **selection** - to be their operands. A single element is selected by pointing at it with the cursor and then clicking the right mouse button. This also causes previously selected elements to be deselected. If the left key is also clicked, their selection is retained. This action is called an **intertick**. To select several elements at once, the cursor is moved from P0 to P1 while the right key is held. Then all elements lying within the rectangle with diagonally opposite corners at P0 and P1 are selected. Selected lines are displayed as dotted lines, selected captions (and macros) by inverse video mode. A macro is selected by pointing at its lower left corner. The command is called **sensitive area**. ### Moving Elements To move (displace) a set of elements, the elements are first selected and then the cursor is moved from P0 to P1 while the middle key is held. The vector from P0 to P1 specifies the movement and is called the **displacement vector**. P0 and P1 may lie in different viewers displaying the same graph. Small displacements may be achieved by using the keyboard's cursor keys. ### Copying Elements Similarly, the selected elements may be copied (duplicated). In addition to pressing the middle key indicating the displacement vector, the left key is interlocked. The copy command may also be used to copy elements from one graph into another graph by moving the cursor from one viewer into another viewer displaying the destination graph. A text item may be copied from a text image into a graphic frame and vice-versa. There exist two ways to accomplish this: 1. First the caret is placed at the destination position, then the text is selected and the middle key is interlocked. 2. First the text is selected, then the caret is placed at the destination position and the middle key is interlocked. ### Shifting the Plane You may shift the entire drawing plane behind the viewer by specifying a displacement vector pressing the middle button (like in a move command) and interlocking the right button. | Action | Mouse Button | |----------------------|---------------| | left (draw line) | draw line | | left (no motion) | set caret | #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 53 Context: ``` left + middle copy selected caption to caret left + right set secondary caret middle + left copy selection middle + right shift drawing plane right select area right (no motion) select object right + middle copy caption to caret right + left select without deselection ## 13.2.2. Menu commands The following commands are displayed in the menu (title bar) of every graphic viewer. They are activated by being pointed at and by clicking the middle button. - **Draw.Delete** The selected elements are deleted. - **Draw.Store** The drawing is written as a file with the name shown in the title bar. - **Draw.Restore** The original file is renamed by appending “.Bak”. - **Draw.Ticks** The frame displays a pattern of dots (ticks) to facilitate positioning. The two viewers in Fig. 13.1 display different parts of the same graphic. The second view was obtained from the generic **System.Copy** command and a subsequent shift of the drawing plane. ![Figure 13.1](path/to/image) *Figure 13.1 Display with graphics duplicated viewers* ## 13.2.3. Further commands The following commands are listed in the text **Draw.Tool**, but may appear in any text. - **Draw.Store name** The drawing in the marked viewer is stored as a file with the specified name. ``` Image Analysis: ### Comprehensive Examination of Visual Content #### 1. Localization and Attribution 1. **Image 1:** Position - Top right quadrant of the document. 2. **Image 2:** Position - Bottom of the document, divided into two sections next to each other. 3. **Image 3:** Position - Second section in the bottom right. #### 2. Object Detection and Classification 1. **Image 1:** - **Objects:** Command list with mouse actions. - **Category:** Text and instructions. - **Key Features:** Detailed description of commands using different mouse button combinations on a graphical interface. 2. **Image 2 & 3:** - **Objects:** Screen display of a graphic viewer illustrating various parts of the same graphic. - **Category:** Interface screenshot. - **Key Features:** Display of rectangles, circles, command lists, and other UI elements arranged over four segmented viewer sections. #### 3. Scene and Activity Analysis 1. **Image 1:** - **Scene:** A list of commands and actions achievable by mouse interactions. - **Activities:** Explanation of functionalities such as 'copy selected caption to caret', 'move selection’, and 'select object'. 2. **Image 2 & 3:** - **Scene:** Interface screenshots showing graphic viewer displaying different parts of an identical graphic. - **Activities:** Representation of what users would see on their screens when interacting with graphic viewer commands, the switching, and redrawing of graphic elements. #### 4. Text Analysis 1. **Extracted Text:** - **Top Text:** Describes mouse commands to manipulate graphics. - Example: "left + middle copy selected caption to caret". - **Middle Text:** Menu commands in a graphics viewer. - Example: "Draw.Delete The selected elements are deleted". - **Bottom Text:** Explanation of figure 13.1. - Example: "The two viewers in Fig. 13.1. display different parts of the same graphic." 2. **Content Analysis:** - The text provides detailed instructions and descriptions for using specific commands within a graphic interface. Each command and its action is clearly documented for user comprehension and application in graphic manipulation. #### 9. Perspective and Composition - **Perspective:** - The perspective is a direct, eye-level view commonly used in instructional documents to ensure clarity. - **Composition:** - The composition is methodical, with text sections followed by illustrative aids (images) providing context and examples to the textual instructions. #### 10. Contextual Significance - **Overall Document:** - This page is part of an instructional document on graphics viewers. - **Image Contribution:** - Each image enhances comprehension by visually representing commands and their effects, aiding users in understanding the interface's functionalities. #### 13. Graph Numbers No graphs with numerical lists were present, making this aspect not applicable. ### Additional Aspects Included - **Prozessbeschreibungen (Process Descriptions):** - **Process:** Instructions and commands for manipulating graphics. - **Description:** Step-by-step detailing of graphical command inputs and outputs using the graphical viewer interface. ### Summary: The document is an instructional guide on using a graphics viewer interface, focusing on mouse commands and their associated functions. The images clarify the text by showcasing the practical application within the interface. The commands range from basic selections to more complex tasks like restoring frames and saving drawings. The composition and contextual relevance of the images significantly aid in user comprehension and practical application of these commands. #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 54 Context: The subsequent commands change attributes of drawing elements, such as line width, text font, and color, and they apply to the most recent selection. ```markdown Draw.SetWidth w default = 1, 0 < w < 7 Draw.ChangeFont fontname Draw.ChangeColor c Draw.ChangeWidth w (0 < w < 7) The ChangeColor command either takes a color number in the range 1..15 or a string as a parameter. It serves to copy the color from the selected character. ## 13.2.4. Macros A macro is a (small) drawing that can be identified as a whole and be used as an element within a (larger) drawing. Macros are typically stored in collections called libraries, from where they can be selected and copied individually. `Draw.Macro lib mac` The macro `mac` is selected from the library named `lib` and inserted in the drawing at the caret's position. An example for the use of macros is drawing electronic circuit diagrams. The basic library file containing frequently used TTL components is called `TTLO.Lib`, and a drawing showing its elements is called `TTLO.Graph` (see Figure 13.2). ![Figure 13.2 Viewer with circuit macros of TTL0 library](path_to_image) ## 13.2.5. Rectangles Rectangles can be created as individual elements. They are frequently used for framing sets of elements. Rectangles consist of four lines that are selectable as a unit. The attribute commands `Draw.SetWidth`, `System.SetColor`, `Draw.ChangeWidth`, and `Draw.ChangeColor` also apply to rectangles. ``` Image Analysis: ### Analysis of the Visual Content #### 1. **Localization and Attribution:** - **Image 1**: - Located prominently below the text under the section "13.2.4 Macros". - Contains diagrams and text. - Numbered as "Image 1." #### 2. **Object Detection and Classification:** - **Image 1**: - Objects Detected: - Circuit diagrams with several components. - Text boxes and interface elements related to circuit design. - Classification: - Electronic components (logic gates, connectors). - Software interface windows. #### 3. **Scene and Activity Analysis:** - **Image 1:** - Entire Scene: - Depicts a software interface displaying circuit diagrams and components. - Activities: - Designing and viewing electronic circuit diagrams. - Main Actors: - The interface itself and its components like logic gates and connectors are the central focus, representing the activity of macro drawing and circuit design. #### 4. **Text Analysis:** - **Image 1:** - Extracted Text: - Various text snippets such as "Add Macro", "Edit Color", circuit names, pin assignments, etc. - Significance: - The text elaborates on the functions and operations available within the software, aiding users in designing and manipulating the electronic circuits. #### 5. **Diagram and Chart Analysis:** - **Image 1:** - Diagrams: - Electronic circuit diagrams showing connections and logical flow. - Some diagrams present logical gates and their interconnections. - Key Insights: - The diagrams represent simple to moderately complex electronic configurations utilizing TTL components. #### **Ablaufprozesse (Process Flows):** - **Image 1:** - Describes the process of designing electronic circuits using schematic diagrams. - Highlights the use of macros in simplifying complex designs by using predefined components. #### **Prozessbeschreibungen (Process Descriptions):** - The text and diagrams together describe the process of drawing and editing circuit designs using TTL components. Instructions include macro selection and insertion, changing attributes of drawing elements, and utilizing libraries. #### **Typen Bezeichnung (Type Designations):** - **TTL (Transistor-Transistor Logic) Components**: - Specifically mentions TTL components and associated tools like `TTL.Lib` for library and `TTL0.Graph` for example drawing. #### **Trend and Interpretation:** - The textual and visual content together suggest a trend towards using macros to streamline electronics design processes, focusing on reusability and efficiency in creating complex circuits. #### **Contextual Significance:** - **Image 1:** - It offers a visual representation to support the textual explanation regarding the usage of macros in circuit design. - Enhances understanding by providing a practical example (`Figure 13.2`). ### Conclusion The analyzed visual content primarily pertains to electronic circuit design, illustrating the use of macros, attributes modification, and libraries for efficient schematic creation. The diagrams and text together serve an educational purpose, explaining how to utilize features of a specific software for circuit design. #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 55 Context: # 13.2.6. Oblique lines, circles, and ellipses Further graphic elements are (oblique) lines, circles, and ellipses. The sensitive area of circles and ellipses is at their lowest point. They are created by the following steps: ## Lines: 1. The caret is placed where the starting point is to lie. 2. A secondary caret is placed at the position of the end. 3. The command `Curves.MakeLine` is activated. ## Circles: 1. The caret is placed where the circle’s center is to lie. 2. A secondary caret is placed, its distance from the center specifying the radius. 3. The command `Curves.MakeCircle` is activated. ## Ellipses: 1. The caret is placed where the center is to lie. 2. A second caret is placed. Its horizontal distance from the first caret specifies one axis. 3. A third caret is placed. Its vertical distance from the first caret specifies the other axis. 4. The command `Curves.MakeEllipse` is activated. # 13.2.7. Spline curves Spline curves are created by the following steps: 1. The caret is placed where the starting point is to lie. 2. Secondary carets are placed at the spline's fixed points (at most 20). 3. The command `Splines.MakeOpen` or `Splines.MakeClosed` is activated. # 13.2.8. Constructing new macros A new macro is constructed and inserted in the library `lib` under the name `mac` as follows: 1. All elements which belong to the new macro are selected. 2. The caret is placed at the lower left corner of the area to be spanned by the macro. 3. A secondary caret is placed at the upper right corner of the area to be spanned. 4. The command `MacroTool.MakeMacro lib` is activated. An existing macro can be decomposed (opened) into its parts as follows: 1. The macro is selected. 2. The caret is placed at the position where the decomposition is to appear. 3. The command `MacroTool.OpenMacro` is activated. # 13.3. The core and its structure Like a text, a graphic consists of elements, subsequently to be called objects. Unlike a text, which is a sequence of elements, a graphic is an unordered set of objects. In a text, the position of an element need not be explicitly indicated (stored); it is recomputed from the position of its predecessor each time it is needed, for example for displaying or selecting an element. In a graphic, each object must carry its position explicitly, as it is independent of any other object in the set. This is an essential difference, requiring a different treatment and much more storage space for an equal number of objects. #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 58 Context: # Modular Structure of Object Management ## Procedures ### handle ```pascal PROCEDURE handle (obj: Object; VAR M: Msg); next: Object END; ``` ### Handler ```pascal PROCEDURE Handler (obj: Object; VAR M: Msg); BEGIN (* this procedure is assigned to the handle field of every line object *) IF M IS DrawMsg THEN drawLine(obj, Line) ELSIF M IS WriteMsg THEN writeLine(obj, M(WriteMsg).R) ELSE ... END; END; ``` ### drawGraphic ```pascal PROCEDURE drawGraphic(first: Object; VAR M: Msg); VAR obj: Object; BEGIN obj := first; WHILE obj <> NIL DO obj.handle(obj, M); obj := obj.next END END drawGraphics; ``` ## Method Record Structure In the present system, a combination of the two schemes presented so far is used. It eliminates the need for individual method fields in each object record as well as the cascaded IF statement for discriminating among the message types. Yet it allows further addition of new methods for later extensions without the need to change the object's declaration. The technique used is to include a single field (called `obj`) in each record (analogous to the handler). This field is a pointer to a method record containing the procedures declared for the base type. At least one of them uses a message parameter, i.e., a parameter of record structure that is extensible. ### Type Definitions ```pascal TYPE Method = POINTER TO MethodDesc; Msg = RECORD END; Context = RECORD END; Object = POINTER TO ObjectDesc; ObjectDesc = RECORD x, y, w, h: INTEGER; selected: BOOLEAN; method: POINTER TO Method; next: Object; END; MethodDesc = RECORD new: Modules.Command; copy: PROCEDURE (obj: Object; to: Object); draw: handle: PROCEDURE (obj: Object; VAR M: Msg); selectable: PROCEDURE (obj: Object; x, y: INTEGER): BOOLEAN; read: PROCEDURE (obj: Object; VAR R: Files.Rider; VAR C: Context); write: PROCEDURE (obj: Object; con: INTEGER; VAR R: Files.Rider; VAR C: Context); END; ``` A single method instance is generated when a new object type is created, typically in the initialization sequence of the concerned module. When a new object is created, a pointer to its record is assigned to the do field of the new object descriptor. A call then has the form `obj.do.write(obj, R)`. This example exhibits the versatility of Oberon's type extension and procedure variable features very well, and it does so without hiding the data structures involved in a dispensable, built-in run-time mechanism. The foregoing deliberations suggest the system’s modular structure shown in Figure 13.3. #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 60 Context: The set of operations applying to selected objects only consist of the following procedures: **Deselect**, **DrawSet** (drawing the selection according to a specified mode), **Change** (changing certain attributes of selected objects like width, font, color), **Move**, **Copy**, **CopyOver** (copying from one graphic into another), and finally **Delete**. Also, there exists the important procedure **Open** which creates a new graphic, either loading a graphic stored as a file, or generating an empty graphic. The declaration of types and procedures that have emerged so far are summarized in the following excerpt of the module's interface definition. ```pascal DEFINITION Graphics; (* excerpt without macros *) IMPORT Files, Fonts, Texts, Modules, Display; CONST NameLen = 32; TYPE Graph = POINTER TO GraphDesc; Object = POINTER TO ObjectDesc; Method = POINTER TO MethodDesc; ObjectDesc = RECORD x, y: INTEGER; c: BYTE; selected, marked: BOOLEAN; de: Method END; Msg = RECORD END; WildMsg = RECORD (Msg) w: INTEGER END; ColorMsg = RECORD (Msg) col: INTEGER END; FontMsg = RECORD (Msg) font: Fonts.Font END; Name = ARRAY NameLen OF CHAR; GraphDesc = RECORD sel: Object; time: INTEGER END; Context = RECORD END; MethodDesc = RECORD module, allocator: Name; new: Modules.Command; copy: PROCEDURE (obj: Object); draw: change: PROCEDURE (obj: Object; VAR msg: Msg); selectable: PROCEDURE (obj: Object; x, y: INTEGER): BOOLEAN; read: PROCEDURE (obj: Object; VAR R: Files.Rider; VAR C: Context); write: PROCEDURE (obj: Object; cnt: INTEGER; VAR R: Files.Rider; VAR C: Context); END; Line = POINTER TO LineDesc; LineDesc = RECORD (ObjectDesc) END; Caption = POINTER TO CaptionDesc; CaptionDesc = RECORD (ObjectDesc) pos, len: INTEGER END; VAR width, res: INTEGER; T: Texts.Text; BEGIN PROCEDURE New(obj: Object); PROCEDURE Add(G: Graph; obj: Object); PROCEDURE Draw(G: Graph; VAR M: Msg); PROCEDURE ThoDo(G: Graph; x, y: INTEGER; Object); PROCEDURE Select(G: Graph; obj: Object); PROCEDURE SelectArea(G: Graph; x0, x1, y0, y1: INTEGER); PROCEDURE Deselect(G: Graph); PROCEDURE DrawSet(G: Graph; VAR M: Msg); END; ``` #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 61 Context: ```markdown # 13.4. Displaying Graphics The base module **Graphics** defines the representation of a set of objects in terms of a data structure. The particulars are hidden and allow the change of structural representation by an exchange of this module without affecting its clients. The problems of displaying a graphic on a screen or a printed page are not handled by this module; they are delegated to the client module **GraphicFrames**, which defines a frame type for graphics that is an extension of **Display.Frame**, just like **TextFrames.Frame** is an extension of **Display.Frame**. In contrast to text frames, however, a graphic instead of a text is associated with it. ```plaintext FrameDesc = RECORD (Display.FrameDesc) graph: Graphics.Graph; Xg, Yg, X1, Y1, x, y: INTEGER; marked, ticked: BOOLEAN; END ``` Every frame specifies its coordinates **X, Y** within the display area, its size by the attributes **W** (width) and **H** (height), and its background color. Just as a frame represents a (rectangular) section of the entire screen, it also shows an excerpt of the drawing plane of the graphic. The coordinate origin need coincide with neither the frame origin nor the display origin. The frame's position relative to the graphic plane's origin is recorded in the frame descriptor by the coordinates **Xg, Yg**. The additional, redundant attributes **x, y, X1, Y1** are given by the following invariants, and they are recorded in order to avoid their frequent recomputation. ``` X1 = X + W, Y1 = Y + H X = X + Xg, Y = Y + Yg ``` **X** (and hence also **X1** and **Y1**) are changed when a viewer is modified, i.e., when the frame is moved or resized. **Xg** and **Yg** are changed when the graph's origin is moved within a frame. The meaning of the various values is illustrated in Figure 13.4. ``` #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 64 Context: # 13.5 The User Interface Although the display is the prime constituent of the interface between the computer and its user, we chose the title of this chapter for a presentation primarily focused on the computer's input, i.e., on its actions instigated by the user's handling of keyboard and mouse, the editing operations. The design of the user interface plays a decisive role in a system's acceptance by users. There is no fixed set of rules which determine the optimal choice of an interface. Many issues are a matter of subjective judgement, and all too often convention is being mixed up with convenience. Nevertheless, a few criteria have emerged as fairly generally accepted. We base our discussion on the premise that input is provided by a keyboard and a mouse, and that keyboard input is essentially to be reserved for textual input. The critical issue is that a mouse - apart from providing a cursor position - allows to signal actions by the state of its keys. Typically, there are far more actions than there are keys. Some mice feature a single key only, a situation that we deem highly unfortunate. There are, however, several ways to "enrich" key states: 1. **Position.** Key states are interpreted depending on the current position of the mouse represented by the cursor. Typically, interpretation occurs by the handler installed in the viewer covering the cursor position, and different handlers are associated with different viewer types. The handler chosen for interpretation may even be associated with an individual (graphic) object and depend on that object's type. 2. **Multiple clicks.** Interpretation may depend on the number of repeated clicks (of the same key), and/or on the duration of clicks. 3. **Interclicks.** Interpretation may depend on the combination of keys depressed until the last one is released. This method is obviously inapplicable for single-key mice. Apart from position dependence, we have quite successfully used interclicks. A ground rule to be observed is that frequent actions should be triggered by single-key clicks, and only variants of them should be signalled by interclicks. The essential art is to avoid overloading this method. Less frequent operations may as well be triggered by textual commands, i.e., by pointing at the command word and clicking the middle button. Even for this kind of activation, Oberon offers two variations: 1. The command is listed in a menu (title bar). This solution is favored when the respective viewer is itself a parameter to the command, and it is recommended when the command is reasonably frequent, because the necessary mouse movement is relatively short. 2. The command lies elsewhere, typically in a viewer containing a tool text. Lastly, we note that any package such as **Draw** is integrated within an entire system together with other packages. Hence it is important that the rules governing the user interfaces of the various packages do not offer unnecessarily, but that they display common ground rules and a common design "philosophy." Draw's conventions were, as far as possible and sensible, adapted to those of the text system. The right key serves for selecting, left for setting the caret, and the middle key for activating general commands, in this case moving and copying the entire graphic. Inherently, drawing involves certain commands that cannot be dealt with in the same way as text fonts. A character is created by typing on the keyboard; a line is created by dragging the mouse while holding the left key. Interclicks left-middle and right-middle are treated in the same way as in the text system (copying a caption from the selection to the caret), and this is not surprising, because text and graphics are properly integrated, i.e., captions can be copied from texts into graphics and vice-versa. #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 66 Context: The design of new macros is a relatively rare activity. Macros are used rather like characters of a font; the design of new macros and fonts is left to the specialist. Nevertheless, it was decided to incorporate the ingredients necessary for macro design in the basic system. They consist of a few procedures only which are used by a tool module called `MacroTool` (see Section 16.3). `MakeMac` integrates all elements lying within a specified rectangular area into a new macro. `OpenMac` reverses this process by disintegrating the macro into its parts. `InsertMac` inserts a specified macro into a library. `NewLib` creates a new, empty library, and `StoreLib` generates a library file containing all macros currently loaded into the specified library. The details of these operations may be examined in the program listings provided later in this chapter. Summarizing, the following procedures are exported from module `Graphics` related to handling macros: - `PROCEDURE GetLibName(VAR Name: ARRAY OF CHAR; replace: BOOLEAN; VAR Lib: Library);` - `PROCEDURE ThisLib(VAR Library: Name: ARRAY OF CHAR; Mach:);` - `PROCEDURE DrawMac(M: Mach; VAR M: Msg);` And the following are added for creating new macros and libraries: - `PROCEDURE NewLib(Name: ARRAY OF CHAR; VAR Library);` - `PROCEDURE StoreLib(VAR Library: FName: ARRAY OF CHAR);` - `PROCEDURE RemoveLibraries;` - `PROCEDURE OpenMac(Mach: M: Mach; G: Graph; x: VAR INTEGER);` - `PROCEDURE MakeMac(G: Graph; x: y, w: INTEGER; Name: ARRAY OF CHAR; Mach:);` - `PROCEDURE InsertMac(m: Mach; Lib: Library; VAR new: BOOLEAN);` ## 13. Object Classes Although surprisingly many applications can be covered satisfactorily with the few types of objects and the few facilities described so far, it is nevertheless expected that a modern graphics system allow the addition of further types of objects. The emphasis lies here on the avoidance instead of change. New facilities are to be providable by the inclusion of new modules without requiring any kind of adjustment, not even recompilation of the existing modules. In practice, their source code would quite likely not be available. It is the triumph of the object-oriented programming technique that this is elegantly possible. The means are the extensible record type and the procedure variable, features of the programming language, and the possibility to load modules and procedure statements within a program, a facility provided by the operating environment. We call, informally, any extension of the type `Object` a class. Hence, the types `Line`, `Caption`, and `Macro` constitute classes. Additional classes can be defined in other modules importing the type `Object`. In every such case, a set of methods must be declared and assigned to a variable of type `MethodDesc`. They form a so-called method suite. Every such module must also contain a procedure, typically a command, to generate a new instance of the new class. This command, likely to be called `Make`, assigns the method suite to the field of the new object. This successful decoupling of additions from the system's base suffices, almost. Only one further kink is unavoidable: When a new graphic, containing objects of a class not defined in the system’s core, is loaded from a file, then that class must be identified, the corresponding module with its handlers must be loaded - this is called dynamic loading - and the object must be generated (allocated). Because the object in question does not already exist at the time of reading the object's attribute values, the generating procedure cannot possibly be installed in the user’s object, it cannot be a member of the method suite. We have chosen the following solution to this problem: 1. Every new class is implemented in the form of a module, and every class is identified by its module name. Every such module contains a command whose effect is to allocate an object of the class, to assign the message suite to it, and to assign the object to the global variable `Graphics.new`. 2. When a graphics file is read, the class of each object is identified and a call to the respective module's allocation procedure derives the desired object. The call consists of two parts: a call to `Modules.ThisMod`, which may cause the loading of the respective class module `M`, and a call of #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 71 Context: and libraries - themselves represented as files - are replaced by indices to font and library dictionaries. These dictionaries establish a context and are constructed while a file is read. They are used only during this process and hence are local to procedure `Load` (or `Open`). For classes, a dictionary listing the respective allocation procedures is constructed in order to avoid repeated calls to determine the pertinent allocator. When a graphic file is generated by procedure `Store`, local dictionaries are constructed of fonts, libraries, and classes of objects that have been written onto the file. Upon encountering a caption, a macro, or any element whose font, library, or class is not contained in the respective dictionary, a pair consisting of index and name is emitted to the file, thereby assigning a number to each name. These pairs are interspersed within the sequence of object descriptions. When the graphic file is read, these pairs trigger insertion of the font, library, or class in the respective dictionary, whereby the name is converted into a pointer to the entity, which is obtained by a loading process embodied by procedures `FontsThis`, `Gell.Lib`, and `GetClass`. Both the `Load` and `Store` procedures traverse the file only once. The files are self-contained in the sense that all external quantities are represented by their names. The format of a graphic file is defined in Extended BNF syntax as follows: ``` file ::= tag stretch. stretch ::= {item} 255. item ::= 0 | 1 (font fontname | 0 | libno libname | 0 2 classno classname allocname) | 1 data (font string | 3 data libno macname | classno data extension). data ::= x y w h color. ``` All class numbers are at least 4; the values 1, 2, and 3 are assigned to lines, captions, and macros. `x`, `y`, `w`, and `h` are two-byte integer attributes of the base type `Object`. The attribute `color` takes a single byte. The first byte of an item being 0 signifies that the item is an identification of a new font, library, or class. If the second byte is 0, a new font is announced, if 1 a new library, and if 2 a new class of elements. The same procedures are used for loading and storing a library file. In fact, `Load` and `Store` read a file stretch representing a sequence of elements which is terminated by a special value (255). In a library file, each macro corresponds to a stretch, and the terminator is followed by values specifying the macro's overall width, height, and its name. The structure of library files is defined in the following syntax: ``` library ::= libtag (macro). macro ::= stretch w h name. ``` The first byte of each element is a class number within the context of the file and identifies the class to which the element belongs. An object of the given class is allocated by calling the class' allocation procedure, which is obtained from the class dictionary in the given context. The class number is used as dictionary index. The presence of the required allocation procedure in the dictionary is guaranteed by the fact that a corresponding index/name pair had preceded the element in the file. The encounter of such a pair triggers the loading of the module specifying the class and its methods. The name of the pair consists of two parts: the first specifies the module in which the class is defined, and it is taken as the parameter of the call to the loader (see procedure `GetClass`). The second part is the name of the relevant allocation procedure which returns an object to variable `Graphics.New`. Thereafter, the data defined in the base type `Object` are read. Data belonging to an extension follow those of the base type, and they are read by the extension's read method. This part must always be headed by a type specifying the number of bytes which follow. This information is used in the case where a requested module is not present; it indicates the number of bytes to be skipped in order to continue reading further elements. A last noteworthy detail concerns the `Move` operation which appears as surprisingly complicated, particularly in comparison with the related copy operation. The reason is our deviation from the principle that a graphics editor must refrain from an interpretation of drawings. Responsible for this #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 73 Context: ```markdown # Bresenham Algorithm for Circle The Bresenham algorithm for a circle given by the equation \(x^2 + y^2 = r^2\) is: ``` x := r; y := 0; d := 1 - r; WHILE x > y DO Dot(x, y); IF d < 0 THEN INC(y); d := d + 2*y + 1; ELSE INC(y); DEC(x); d := d + 2*y - 2*x + 1; END; END ``` # Definition of Curves ```pascal TYPE Curve = POINTER TO CurveDesc; ``` ## CurveDesc Record ```pascal CurveDesc = RECORD (Graphics.ObjectDesc) kind : INTEGER END; ``` - **kind**: 0 (up-line), 1 (down-line), 2 (circle) # VAR ```pascal method: Graphics.Method; ``` ## Procedures ```pascal PROCEDURE MakeLine; PROCEDURE MakeCircle; END Curves. ``` #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 74 Context: # 14 Building and Maintenance Tools ## 14.1 The Startup Process An aspect usually given little attention in system descriptions is the process of how a system is started. Its choice, however, is itself an interesting and far from trivial design consideration and will be described here in some detail. Moreover, it directly determines the steps in which a system is developed from scratch, mirroring the steps in which it builds itself up from a bare store to an operating body. The startup process typically proceeds in several stages, each of them bringing further facilities into play, raising the system to a higher level towards completion. The term for this strategy is **boot strapping** or, in modern computer jargon, **booting**. 1. **Stage 0** is initiated when power is switched on or when the reset button is pressed and released. To be precise, power-on issues a reset signal to all parts of the computer and holds it for a certain time. Pushing the reset button therefore appears like a power-on without power having been switched off. Release of the reset signal triggers the built-in FPGA hardware to load a short configuration bit-stream from a ROM residing on the Spartan board, called the **platform flash**, into the BRAM within the FPGA. This program is called **boot loader**. Being stored in a ROM, it is always present. The BRAM is address-mapped onto an upper part of the address space, and the RISC processor starts execution at this address. 2. In **Stage 1**, the boot loader loads the **inner core**, which consists of modules **Kernel**, **FileDir**, **Files**, and **Modules**. The loader first inspects the link register. If its value is 0, a cold start is indicated. (If the value of the link register is not 0, this signals an abort caused by pressing button 3 on the board). Then loading is skipped and control is immediately returned to the Oberon command loop. The disk (SD-card, SPI) is initialized. The boot loader terminates with a branch to location 0, which transfers control to the just loaded module **Modules**, the regular loader. 3. **Stage 2** starts with the initialization body of module **Modules** which calls the bodies of **Kernel**, **FileDir** and **Files**, establishing a working file system. Then it calls itself, requesting to load the central module **Oberon**. This implicitly causes the loading of its own imports, namely **Input**, **Display**, **Viewers**, **Fonts**, and **Texts**, establishing a working viewer and text system. This loading of the outer core must be interpreted as the continuation of the loading of the inner core. To allow proper continuation, the boot loader has deposited the following data in fixed locations: | Address | Description | |---------|---------------------------------------------------------------| | 0 | A branch instruction to the initializing body of module **Modules** | | 12 | The limit of available memory | | 16 | The address of the end of the module space loaded | | 20 | The current root of the links of loaded modules | | 24 | The current limit of the module area | 4. In **Stage 3**, **Oberon** calls the loader to load the tool module **System**, and with its imports **MenuViewers** and **TextFrames**. The initialization of **System** causes the opening of the viewers for the system tool and the system log. Control then returns to Oberon and its central loop for polling input events. Normal operation begins. The booting process is summarized in Figure 14.1. #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 76 Context: Still, how did the hardware configuration data and the boot loader get into the Flash ROM? This step requires the help of proprietary tools of the FPGA manufacturer. Regrettably, their incantation ceremony typically is rather complex. After all necessary Verilog models have been synthesized, the result is the configuration file `RISCTop.bit`. The necessary source files are: - `RISCTop.v` - `RISC.v` - `Multiplier.v` - `Divider.v` - `FP-Multiplier.v` - `FP-Divider.v` - `dbram32.v` - `RS232T.v` - `RS232R.v` - `SP1K.v` - `XGVS.v` - `P2SV.v` - `RISC.ucf` Thereafter, the boot loader is compiled and, together with the result of the configuration of the RISC hardware, loaded into the configuration memory of the FPGA. This Stage 0 is partly done with proprietary software (dependent on the specific FPGA) and is described in a separate installation guide. ``` Stage 0 +-----------------+ | | | RISCTop.bit | | ins1.mem | | | +-----------------+ | v +------------------------+ | FlashRISC_cmd | +------------------------+ | v +-----------------+ | RISC.bit | +-----------------+ | v +----------------------+ +-----------------+ | Xilinx tool | | RS-232 link | | download.cmd | +-----------------+ +----------------------+ | | v | +-------------------+ | | BRAM | | | boot loader | | +-------------------+ | | | v | +-------------------+ | | Memory | | | Kernel File | | | Modules Oberon | | +-------------------+ | v +--------------------+ | Config mem | | FPGA config | +--------------------+ Figure 14.2 Booting from host computer A simple boot loader reading from the RS-232 line and using the stream format described above is shown here: ```pascal MODULE Bootload; IMPORT SYSTEM; CONST MT = 12; SP = 14; MemLim = 0E700H; (* w = 60; len = 60; data = 56; ctrl = 52; ('device addresses') *) PROCEDURE Recint(VAR x: INTEGER); VAR z, y: INTEGER; BEGIN z := 0; y := 4; REPEAT i := 0; REPEAT UNTIL SYSTEM.BIT(crt, 0); SYSTEM.GET(data, y); z := ROR(z,y,8) UNTIL i = 0; x := z END Recint; PROCEDURE Load; VAR len, adr, dat: INTEGER; BEGIN Recint(len); WHILE len > 0 DO Recint(dat); REPEAT Recint(data); SYSTEM.PUT(dat, adr); adr := adr + 4; len := len - 4 UNTIL len = 0; Recint(len) END Load; ``` #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 79 Context: # 14.3 Maintenance Tools An important prerequisite for Stage 2 (and the following stages) in the boot process has not been mentioned above. Recall that the initialization of module `FileDir` constructs the disk sector reservation table in the `Kernel` from information contained on the disk. Obviously, its prerequisite is an intact, consistent file directory. A single unreadable, corrupted file directory or file header sector lets this process fail, and booting becomes impossible. To cope with this (fortunately rare) situation, a maintenance tool has been designed: module `DiskCheck`. ## DiskCheck `DiskCheck` is organized similarly to Oberon as a simple command interpreter, but it imports only `Kernel` and `RS232`. Hence, booting involves only Stages 1 and 2 without any access to the disk. Operating `DiskCheck` requires care and knowledge of the structure of the file system (Chapter 7). The available commands are as follows: | parameters | action | |------------|---------------------------------| | 0 | send and mirror integer (test) | | 1 a, n | show (in hex) M[a], M[a+4], ..., M[a + n*4] | | 2 secno | show disk sector | | 3 secno | show head sector | | 4 secno | show directory sector | | 5 | traverse directory | | 6 secno | clear header sector | | 7 secno | clear directory (root pack) | The essential command is the file directory traversal (5). It lists all faulty directory sectors, showing their numbers. It also lists faulty header sectors. No changes are made to the file system. If a faulty header is encountered, it can subsequently be cleared (6). Thereby, the file is lost. It is not removed from the directory, though. But its length will be zero. Program `DiskCheck` must be extremely robust. No data read can be assumed to be correct, no index can be assumed to be within its declared bounds, no sector number can be assumed to be valid, and no directory or header page may be assumed to have the expected format. Guards and error diagnostics take a prominent place. Whereas a faulty sector in a file in the worst case leads to the loss of that file, a fault in a sector carrying a directory page is quite disastrous. Not only because the files referenced from that page, but also those referenced from descendant pages become inaccessible. A fault in the root page even causes the loss of all files. The catastrophe is of such proportions that measures should be taken even if the case is very unlikely. After all, it may happen, and it indeed has occurred. The only way to recover files that are no longer accessible from the directory is by scanning the entire disk. In order to make a search at all possible, every file header carries a mark field that is given a fixed, constant value. It is very unlikely, but not entirely impossible, that data sectors which happen to have the same value at the location corresponding to that of the mark, may be mistaken to be headers. #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 80 Context: The tool performing such a scan is called **Scavenger**. It is, like **DiskCheck**, a simple command interpreter with the following available commands: | parameters | action | |------------|--------------------------------------| | 0 s | send and mirror integer (test) | | 1 n | Scan the first n sectors and collect headers | | 2 - | Display names of collected files | | 3 - | Build new directory | | 4 - | Transfer new directory to the disk | | 5 - | Clear display | During the scan, a new directory is gradually built up in primary store. Sectors marked as headers are recorded by their name and creation date. The scavenger is the reason for recording the file name in the header, although it remains unused there by the Oberon System. Recovery of the date is essential because several files with the same name may be found. If one is found with a newer creation date, the older entry is overwritten. Command **W** transfers the new directory to the disk. For this purpose, it is necessary to have free sectors available. These have been collected during the scan: both old directory sectors (identified by a directory mark similar to the header mark) and overwritten headers are used as free locations. The scavenger has proven its worth on more than one occasion. Its main drawback is that it may rediscover files that had been deleted. The deletion operation by definition affects only the directory, but not the file. Therefore, the header carrying the name remains unchanged and is discovered by the scan. All in all, however, it is a small deficiency. ## Reference 1. N. Wirth. Designing a System from Scratch. *Structured Programming*, 1, (1989), 10-18. #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 81 Context: # 15 Tool and service modules In this chapter, a few modules are presented that do not belong to Oberon's system core. However, they belong to the system in the sense of being basic, and of assistance in some way, either to construct application programs, to communicate with external computers, or to analyze existing programs. ## 15.1 Basic mathematical functions Module `Math` contains the basic standard functions that had been postulated already in 1960 by Algol 60. They are: - `sqrt(x)` | the square root - `exp(x)` | the exponential function - `ln(x)` | the natural logarithm - `sin(x)` | the sine function - `cos(x)` | the cosine function They are presented here only briefly without discussing their approximation methods. However, we point out how advantage can be taken from knowledge about the internal representation of floating-point numbers. ### 15.1.1 Conversion between integers and floating-point numbers The Oberon System adopts the standard format postulated by IEEE. Here we restrict it to the 32-bit variant. A floating-point number `x` consists of 3 parts: - `s` | the sign | 1 bit - `e` | the exponent | 8 bits - `m` | the mantissa | 23 bits Its value is defined as \[ x = (-1)^s \times 2^{e-127} \times (1.m) \] A number is in normalized form, if its mantissa satisfies \(1.0 \leq m < 2.0\). It is assumed that numbers are always normalized, and therefore the leading 1-bit is omitted. The exception is the singular value 0, which cannot be normalized. It must therefore be treated as a special case. It follows that integers and floating-point numbers are represented quite differently, and that conversion operations are necessary to transfer a number from one format to the other. This is the reason why the Oberon language keeps the two types INTEGER and REAL separate. Conversion must be explicitly specified by using the two predefined functions: - \( n = \text{FLOOR}(x) \quad \text{REAL} \rightarrow \text{INTEGER} \) - \( x = \text{FLT}(n) \quad \text{INTEGER} \rightarrow \text{REAL} \) Note: `FLOOR(x)` rounds toward -inf. For example `FLOOR(1.5) = 1`, `FLOOR(-1.5) = -2`. The RISC processor does not feature specific instructions implementing these functions. Instead, the compiler generates inline code using the FAD instruction with special options suppressing normalization. This option is specified by the `u` and `v` modifier bits of the instruction. The `FLOOR` function is realized by adding 0 with an exponent of 127 + 24 and suppressing the insertion of a leading 1-bit (i.e. `u = 1`). This causes the mantissa of the argument to be shifted right until its exponent is equal to 151. The RISC instructions are: ``` MOV R1 R0 4800H R1 = 48000000H FAD R0 R0 R1 ``` The `FLT` function is implemented also by adding 0 with an exponent of 151 and forced insertion of a leading 1-bit (i.e. `v = 1`). #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 83 Context: ``` PROCEDURE expX: REAL; REAL; CONST c1 = 1.44269504088896; // (1 / ln(2) ) p0 = 1.58197615902832; p1 = 2.20257774822299; p2 = 3.2081636692042E-2; q0 = 4.3688938420652; q1 = 3.3318938202161E-2; VAR n: INTEGER; p, y: REAL; BEGIN n := FLOOR(x * c1); y := FLT(n); y := y - y * y / (p0 + (p1 * y + p0) * y); p := (p0 + q1 * y + q0 - p) * 0.5; PACK(p, n); RETURN p END expX; 15.1 The logarithm Again we take advantage of the presence of an exponent in the floating-point representation and use the equations ln (a * b) = ln a + ln b ln (2^x) = log(2^x * m) x ln(2) = x * ln(2) + ln m PROCEDURE lnX: REAL; REAL; CONST c1 = 0.707106781186547; // (1 / sqrt(2) ) c2 = 0.693147180559945; // (ln(2) ) p0 = 0.1617496772011; p1 = 9.9466599001E-1; p2 = 3.843770041E-1; q0 = 4.589734456E1; q1 = 1.678165560E1; q2 = -2.076339789E1; VAR x: REAL; j: INTEGER; y: REAL; BEGIN ASSERT (x > 0.0); UNPK(x, e); IF x < (THRESHOLD * 2.0) = e * 1.0E-1 THEN x := x * 1.0E-1; y := x * (FLT(y) + x / ((p2 * x + p0) / ((x + q2) * x + q1) + q0)); RETURN y END lnX; 15.1. The sine function Figure 15.1 Sine function y = sin(x) First, the argument x is transposed into the interval [0, π/4] by computing ``` #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 85 Context: ``` REPEAT UNTIL SYSTEM.BIT(stat, 0); SYSTEM.GET(data, x); END Dec; PROCEDURE RecName(VAR s: ARRAY OF CHAR); VAR i: INTEGER; x: BYTE; BEGIN i := 0; RecX(i); WHILE x <> 0 DO BEGIN s[i] := CHR(x); INC(i); RecX; END; s[i] := 0; END RecName; PROCEDURE Send; BYTE; BEGIN REPEAT UNTIL SYSTEM.BIT(stat, 1); SYSTEM.PUT(data, x); END Send; PROCEDURE Task; VAR len, n: INTEGER; x, ack, code: BYTE; name: ARRAY[0..31] OF CHAR; F: Files.File; Ri: Files.Rider; buf: ARRAY[0..255] OF BYTE; BEGIN IF SYSTEM.BIT(stat, 0) THEN (* "byte available" *) Rec(code); code := SND THEN (* "send file" *) RecName(name); F := Files.Old(name); IF F = NIL THEN Send(ACK); len := Files.Length(F); Files.SetR(F, 0); REPEAT IF len > 1k THEN len := 1k; ELSE len := len; Send(len); n := len; len := len - 1; WHILE n > 0 DO Files.Read(buf, x); Send(buf); DEC(n); END UNTIL len < 1k; ELSE Send(1); END END; ELSE code := REC THEN (* "receive file" *) RecName(name); IF F = NIL THEN Files.SetR(F, 0); Send(ACK); REPEAT Rec(len); len := x - 1; WHILE len > 0 DO buf[i] := 0; INC(i); END; WHILE i < len DO Files.WriteByte(F, buf[i]); INC(i); END UNTIL len < 255; Files.Register(F); Send(ACK); ELSE Send(NAK); END END; ELSE code := REC THEN Send(ACK) (* "for testing" *) END; END; END Task; PROCEDURE Run; BEGIN Oberon.Inst(); Texts.WriteString(W, "PCLink started"); Texts.WriteLn(""); Texts.Append(Oberon.Log, W.buf); END Run; PROCEDURE Stop; ``` #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf Page: 86 Context: # 15.3. A generator of graphic macros The module `MacroTool` serves to create macros for the graphic system (Ch. 13). It provides the commands `OpenMacro`, `MakeMacro`, `LoadLibrary`, and `StoreLibrary`. - **OpenMacro** decomposes the selected macro into its elements and places them at the position of the caret. This command is typically the first if an existing macro is to be modified. - **MakeMacro** `M` collects all selected objects in the frame designated by the star pointer and unites them into macro `M`. This macro is displayed at the caret position and inserted into library `L`. If no such library exists, a new one is created. - **LoadLibrary** `L` loads the library `L` (under file name `L.Lib`). Note that a library must have been stored before it can be loaded. - **StoreLibrary** stores library `L` (with filename `L.Lib`). The required modules are `Texts`, `Oberon`, `Graphics`, `GraphicFrames`. #################### File: UNIX%20Application%20and%20System%20Programming%2C%20lecture%20notes%20-%20Stewart%20Weiss%20%28PDF%29%20chapter_05.pdf Page: 3 Context: # UNIX Lecture Notes ## Prof. Stewart Weiss ### Chapter 5 Interactive Programs and Signals #### 5.2.1 Two Different Paradigms Consider the kind of terminal-based program in which the program repeatedly prompts the user for input and takes an action accordingly. One of the user responses such programs expect is some type of quit signal, which typically breaks the loop and ends the program. This can be modeled by a control structure such as the following: ``` while (true) { prompt the user to do something wait for the user to respond if user’s response is to quit break the loop and quit handle the response } ``` The input part of this loop usually results in the process being blocked on input, but it does not have to be designed this way. It might look like: ``` while (true) { prompt the user to do something if the user responded handle the response otherwise do other things } ``` In this paradigm, the program checks whether there is input and if there is, responds to it, and if not, it does something else. This approach requires the ability to check if there is input without blocking while waiting for it. In short, it requires a type of input operation known as non-blocking input, which will be discussed below. Regardless of which input method is used, programs such as video games, ATM machines, and text editors respond immediately to user key presses, rather than waiting for the Enter key to be pressed. They run in non-canonical mode, so they do not buffer input characters. Usually, they do not echo the input characters when these characters behave like function keys. Also, they usually ignore illegal key presses. Thus, one task in designing interactive programs is to determine how to control the state of the terminal in this way. But this is not enough. There is a big difference between a video game and a text editor, having to do with their relationship to time. We can distinguish between two kinds of interactive programs: those whose state is independent of time, and those whose state depends upon time. Any program that animates, in any way, is time-dependent; its state changes as a function of time. Programs that terminate or advance to a different state if the user does not respond within a certain amount of time are also time-dependent, because their state changes as a function of time. Video games are time-dependent. In contrast, a text editor is usually time-independent; it has no time-outs and no animation of any kind. Programming with time is more complex than programming in a time-independent way because it requires knowledge of several different parts of the kernel API. Before we tackle this problem, we will explore a simpler one, namely how to write a text editor. 1. I think about vi for example, and how it behaves in Command mode; you type `i` and it moves the cursor without displaying the letter, or more, when you type a space character and it advances a screen’s worth of lines. --- This work is copyrighted by Stewart Weiss and licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. Image Analysis: ### Detailed Analysis of the Visual Content 1. **Localization and Attribution:** - **Image Position and Numbering:** - The document contains one image. - This image is identified as **Image 1**. 2. **Text Analysis:** - **Detected Text:** The image contains textual content formatted as lecture notes on UNIX programming. The detected text is as follows: ``` UNIX Lecture Notes Prof. Stewart Weiss Chapter 5 Interactive Programs and Signals 5.2.1 Two Different Paradigms Consider the kind of terminal-based program in which the program repeatedly prompts the user for input and takes an action accordingly. One of the user responses such programs expect is some type of quit signal, which typically breaks the loop and ends the program. This can be modeled by a control structure such as the following: while (true) { prompt the user to do something wait for the user to respond if user’s response is to quit break the loop and quit handle the response } The input part of this loop usually results in the process’s being blocked on input, but it does not have to be designed this way. It might look like while (true) { prompt the user to do something if the user responded handle the response otherwise do other things } In this paradigm, the program checks whether there is input and if there is, responds to it and, if not, it does something else. This approach requires the ability to check if there is input without blocking while waiting for it. In short, it requires a type of input operation known as non-blocking input, which will be discussed below. Regardless of which input method is used, programs such as video games, ATM machines, and text editors respond immediately to user key presses, rather than waiting for the Enter key to be pressed. They run in non-canonical mode, so they do not buffer input characters. Usually, they do not echo the input characters when these characters behave like function keys 1. Also, they usually ignore illegal key presses. Thus, one task in designing interactive programs is to determine how to control the state of the terminal in this way. But this is not enough. There is a big difference between a video game and a text editor, having to do with their relationship to time. We can distinguish between two kinds of interactive programs: those whose state is independent of time, and those whose state depends upon time. Any program that animates, in any way, is time-dependent; its state changes as a function of time. Programs that terminate or advance to a different state if the user does not respond within a certain amount of time are also time-dependent, because their state changes as a function of time. Video games are time-dependent. In contrast, a text editor is usually time-independent; it has no time-outs and no animation of any kind. Programming with time is more complex than programming in a time-independent way because it requires knowledge of several different parts of the kernel API. Before we tackle this problem, we will explore a simpler one, namely how to write a text editor. 1 Think about vi for example, and how it behaves in Command mode: you type a `j’ äand it moves the cursor without displaying the letter, or more, when you type a space character and it advances a screen’s worth of lines. This work is copyrighted by Stewart Weiss and licensed under the Creative Commons Attribution- ShareAlike 4.0 International License. 3 ``` - **Content Analysis:** - The document is discussing two paradigms in the context of interactive terminal-based UNIX programs. - It presents examples of control structures that handle user input and describe how these structures can be designed to manage program flow. - The text explains the concept of non-blocking input operations and the differences between time-dependent and time-independent programs. 4. **Code Blocks:** - **Code Snippet 1:** ``` while (true) { prompt the user to do something wait for the user to respond if user’s response is to quit break the loop and quit handle the response } ``` - **Explanation:** - This snippet represents a typical loop for prompting user action. - It waits for the user to respond and processes their input, breaking the loop if the user chooses to quit. - **Code Snippet 2:** ``` while (true) { prompt the user to do something if the user responded handle the response otherwise do other things } ``` - **Explanation:** - This snippet shows an alternative approach where the program checks if the user has responded and acts accordingly without blocking. ### Summary: The document page focuses on explaining different paradigms of handling user input in UNIX terminal-based programs, demonstrating various control structures and explaining the concept of non-blocking input and time-dependency in programming. #################### File: UNIX%20Application%20and%20System%20Programming%2C%20lecture%20notes%20-%20Stewart%20Weiss%20%28PDF%29%20chapter_05.pdf Page: 4 Context: # UNIX Lecture Notes **Prof. Stewart Weiss** **Chapter 5 Interactive Programs and Signals** ## 5.2.2 A Simple Text Editor: simplevi The `vi` text editor is a very complicated piece of software, but we can create an extremely stripped-down version of it and still learn quite a bit in the process. We will call our editor `simplevi`. This simple editor will allow the user to insert characters anywhere in a text document, but it will not provide a means of deleting characters. This is just a minor extension to the program. Also, it will not open an existing text file, but will instead create a new file each time it is invoked. Adding a feature to open a file does not provide much more insight into the interactive design of the program, but it does make the program larger. As much as possible, the features that `simplevi` does implement will have the same semantics as those in `vi`. ### 5.2.2.1 Features of simplevi The `simplevi` program allows a user to create a file in a manner similar to `vi`. It has only an insert command and does not presently support deletion. Like `vi`, it is always in exactly one of three possible modes: - input mode - command mode - last_line mode Each mode is now described briefly. #### Command Mode The initial mode is command mode. In `command_mode` one can enter the following keystrokes/commands: | Key | Semantics | |----------------------|-------------------------------------------------------------------| | `i` | changes to input mode. | | `.` | changes to lastline mode. | | `h`, backspace, or left-arrow key | moves left until the first character in the text line. If a line wraps, it follows the wrapped text backwards. | | `1`, spacebar, or right-arrow key | moves right until the last character in the text line. If a line wraps, it follows the wrapped text forwards. | | `x` or up-arrow key | moves to the text line above, to the same position relative to the start of the text line, unless that text line is shorter than the current one, in which case it is placed at the end of the text line. Scrolling takes place as necessary. | | `j` or down-arrow key | moves to the next text line below, using the same rule as for the up arrow when deciding the horizontal position. Scrolling takes place as necessary. | | `Ctrl-D` | Does nothing except display the message that it was pressed. | | `Ctrl-C` | Does nothing except display the message that it was pressed. | | `Ctrl-H` | Can be used to display a help screen, but at present just shows a one-line text message. | This work is copyrighted by Stewart Weiss and licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. Image Analysis: ### Image Analysis 1. **Localization and Attribution:** - There is only one image on the page, which we will refer to as **Image 1**. 2. **Object Detection and Classification:** - **Text:** The image contains a large amount of text divided into headings, paragraphs, bullet points, and a table. - **Table:** The image includes a table with two columns labeled "Key" and "Semantics." 3. **Scene and Activity Analysis:** - **Scene:** The image depicts a page from a set of lecture notes for a UNIX course. It appears to be an instructional text on a simplified text editor called "simplevi." - **Activities:** The text describes the functionalities and features of the simplified text editor, along with key commands and their semantics. 4. **Text Analysis:** - **Detected Text:** - **Headers and Subheaders:** - "UNIX Lecture Notes" - "Chapter 5 Interactive Programs and Signals" - "5.2.2 A Simple Text Editor: simplevi" - "5.2.1 Features of simplevi" - "Command Mode" - **Paragraphs:** - Describes the text editor "simplevi" and its basic functionality, contexts for use, and the features it does or does not include. - **Bulleted List:** - Lists the modes available in simplevi: input mode, command mode, and last_line mode. - **Table:** - Details the keystrokes and their corresponding semantics within Command Mode: - `i`: changes to input mode. - `:`: changes to lastline mode. - `h, backspace, or left-arrow key`: moves left until the first character in the text line. If a line wraps, it follows the wrapped text backward. - And many more similar command keys with their respective functions. - **Content Analysis:** - The text serves as an educational resource on a simple text editor, illustrating the basics of its use. This context is valuable for students or learners who are being introduced to text editors in UNIX environments. 5. **Diagram and Chart Analysis:** - There are no diagrams or charts in the image. 6. **Product Analysis:** - No products are depicted in this image. 7. **Anomaly Detection:** - There are no noticeable anomalies or unusual elements within the image. 8. **Color Analysis:** - The image is primarily in grayscale (black text on a white background) with some headings in bold for emphasis. The use of a grayscale color scheme is standard for textual or instructional materials and ensures readability. 9. **Perspective and Composition:** - **Perspective:** The image seems to be a direct scan or screenshot of a page from a document, presented in a straight, front-facing view. - **Composition:** The text is neatly organized with clear headings, subheadings, paragraphs, and a table. The table is centrally located and well-structured for easy reading and understanding. 10. **Contextual Significance:** - **Role in Document:** The image appears to be part of a chapter from UNIX lecture notes. It contributes instructional information on a command-line text editing program, which is relevant knowledge for those studying UNIX systems. - **Contribution:** It provides detailed instructions and commands, aiding learners in understanding and using the "simplevi" text editor effectively. 11. **Metadata Analysis:** - No metadata is available within the image itself. 12. **Graph and Trend Analysis:** - There are no graphs in the image. 13. **Graph Numbers:** - No graphs are included, hence no data points to list. ### Additional Aspects - **Ablaufprozesse (Process Flows):** - Process flows are depicted through the sequence of commands and their effects in the "Command Mode" section. - **Prozessbeschreibungen (Process Descriptions):** - The process of using the simplevi text editor is described, including switching between different modes and executing various commands. - **Typen Bezeichnung (Type Designations):** - Types or categories are designated through the various modes of the text editor and the associated keyboard commands. - **Trend and Interpretation:** - Trends are inherent in the design and operation of the text editor, showcasing a simplified structure that focuses on essential command-line operations. - **Tables:** - The table concisely lists command keys and their functions, providing an essential quick reference for users. This comprehensive examination of the image covers the key aspects you've requested. #################### File: UNIX%20Application%20and%20System%20Programming%2C%20lecture%20notes%20-%20Stewart%20Weiss%20%28PDF%29%20chapter_05.pdf Page: 12 Context: # UNIX Lecture Notes **Prof. Stewart Weiss** **Chapter 5: Interactive Programs and Signals** ## Listing 5.4: update_buffer_index() ```c void update_buffer_index( Buffer *buffer ) { int totalchars = 0; int i = 0; while ( i < buffer->cur_line ) { totalchars += buffer->line_len[i]; i++; } totalchars += buffer->index_in_cur_line; buffer->index = totalchars; } ``` Similarly, it is also necessary to get the cursor's actual window coordinates when all that is known are the current line number and the offset within that line. This is the case, for example, when the down arrow key is pressed and the cursor must be moved to a new text line. It is possible that the cursor would actually be below the last visible line. The only way to know this is to calculate its window coordinates and compare them to the bottom of the screen. The following function is our means of getting the cursor position. ## Listing 5.5: get_cursor_at() ```c void get_cursor_at( Buffer *buf, Window win, int index, int lineno, Cursor *curs ) { int total_lines_before = 0; int rows_in_current_textline = 0; int i; /* The first line is the one at the top of the window, whose index is win.line_at_top; initially 0 */ for ( i = win.line_at_top; i < lineno; i++ ) { if ( buf->line_len[i] < win.cols ) total_lines_before++; else total_lines_before += (int) ceil((double)buf->line_len[i]/win.cols); } rows_in_current_textline = index / win.cols; curs->y = total_lines_before + rows_in_current_textline; curs->x = index - rows_in_current_textline * win.cols; } ``` There are four movements that the program has to implement: up, down, left, and right. We show just one of these here. The complete program is in the appendix. The up and down movements are a bit more complex than left and right. When the down arrow key is pressed, or the `j` key, the cursor must be moved to the position in the text line below at the same offset relative to the beginning of the line, unless that line is shorter. This work is copyrighted by Stewart Weiss and licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. Image Analysis: ### Analysis of the Attached Visual Content #### 1. Localization and Attribution: - **Single Image**: The document features only one page with text and code snippets. #### 2. Object Detection and Classification: - **Detected Objects**: - Text paragraphs - Code blocks - Headers and footers #### 4. Text Analysis: - **Detected Text**: - **Header**: - Left: "UNIX Lecture Notes" - Center: "Chapter 5 Interactive Programs and Signals" - Right: "Prof. Stewart Weiss" - **Footer**: - Left: "This work is copyrighted by Stewart Weiss and licensed under the Creative Commons Attribution-ShareAlike 4.0 International License." - Page Number: "12" - **Main Text**: - The text explains a specific function `update_buffer_index()` which updates an index in a buffer only when an insertion or other operation is performed on the text. - It details a process to calculate the cursor’s actual window coordinates, important for getting the current line number and offset within that line. It also explains cursor movement implementations (up, down, left, right). - **Code Snippets**: - **Listing 5.4: `update_buffer_index()`** ```c void update_buffer_index( Buffer *buffer ) { int totalchars = 0; int i = 0; while ( i < buffer->cur_line ) { totalchars += buffer->line_len[i]; i++; } totalchars += buffer->index_in_cur_line; buffer->index = totalchars; } ``` - **Listing 5.5: `get_cursor_at()`** ```c void get_cursor_at( Buffer buf, Window win, int index, int lineno, Cursor *curs ) { int total_lines_before = 0; int rows_in_current_textline = 0; int i; /* The first line is the one at the top of the window, whose index is win.line_at_top; initially 0. */ for ( i = Win.line_at_top; i < lineno; i++ ) { if ( buf.line_len[i] < win.cols ) total_lines_before++; else total_lines_before += (int) ceil((double)buf.line_len[i]/win.cols); } rows_in_current_textline = index/win.cols; curs->r = total_lines_before + rows_in_current_textline; curs->c = index - rows_in_current_textline * win.cols; } ``` #### 6. Product Analysis: - **Products**: This analysis does not apply as there are no products depicted in the visual content. #### 8. Color Analysis: - **Color Composition**: - The document is primarily in grayscale, with black text on a white background. This standard academic or professional document color scheme ensures readability and focus on the text content. #### 9. Perspective and Composition: - **Perspective**: - The image presents a typical scanned or snapshot view of a text document presented directly from an overhead perspective. - **Composition**: - The text is arranged in paragraphs with appropriate headings, followed by code snippets. Listings and explanations are clearly aligned. #### 11. Metadata Analysis: - **Metadata**: - The page comes from “UNIX Lecture Notes” by Prof. Stewart Weiss. - Chapter and focus: "Chapter 5 Interactive Programs and Signals". - Large emphasis is placed on properly licensing the document under Creative Commons. #### Additional Aspects: - **Prozessbeschreibungen (Process Descriptions)**: - The text thoroughly describes processes for handling buffer indexing and cursor positioning within a text editor. This exhaustive analysis aimed to provide comprehensive detail based on each specified aspect, focusing primarily on textual and contextual analysis due to the nature of the visual content. #################### File: UNIX%20Application%20and%20System%20Programming%2C%20lecture%20notes%20-%20Stewart%20Weiss%20%28PDF%29%20chapter_05.pdf Page: 22 Context: # UNIX Lecture Notes **Prof. Stewart Weiss** ## Chapter 5 Interactive Programs and Signals ### 5.2.5 A Test Program We will build a program in which we can test the effects of changing both the terminal driver’s attributes and the open connection’s attributes. The main program will be a test driver that allows the user to control the state of the terminal and terminal connection by various command line options, and repeatedly runs a simple function, which we will call `get_response()`, that reads user input in the given state of the terminal and connection. The main program will have a few bells and whistles besides. The program will have separate functions for controlling the state of the control terminal and for changing the attributes of the file connection to the terminal device. The main program will have a loop to allow us to experiment with the `get_response()` function until we are satisfied that we understand how it behaves under the given settings. There are several pieces to the program, which we present in a bottom-up approach. First, we combine the `save_restore_tty()` and `set_non_block()` functions into a single function that saves and restores both the terminal settings and the file descriptor flags. It uses the same macros as before: ```c void save_restore_tty(int fd, int action, struct termios *copy) { static struct termios original_state; static int original_flags = -1; static int retrieved = FALSE; if (action == RETRIEVE) { retrieved = TRUE; tcgetattr(fd, &original_state); original_flags = fcntl(fd, F_GETFL); if (copy != NULL) *copy = original_state; } else if (retrieved && action == RESTORE) { tcsetattr(fd, TCSADRAIN, &original_state); fcntl(fd, F_SETFL, original_flags); } else { fprintf(stderr, "Bad action to save_restore_tty().\n"); } } ``` We will change our `modify_termios()` function so that it can be given a structure whose members describe the terminal settings: ```c typedef struct tty_opts_tag { int min; /* value to assign to MIN */ int time; /* value to assign to TIME */ int echo; /* value to assign to echo [01] */ int canon; /* value to assign to canon [01] */ struct termios tty_opts; } tty_opts; ``` *This work is copyrighted by Stewart Weiss and licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.* Image Analysis: ### Analysis **Localization and Attribution:** - **Image 1**: The entire content on the page. **Text Analysis:** - The image contains a text-based excerpt from "UNIX Lecture Notes" authored by "Prof. Stewart Weiss". - Title: "Chapter 5 Interactive Programs and Signals". - Subsection: "5.2.5 A Test Program". - Main Content: - The text explains a test program that experiments with changing terminal driver's attributes and open connection attributes. - It details how the user interface for the program will be designed to repeatedly perform an action (`get_response()`) and describes the structure for controlling terminal states. - There is a code snippet demonstrating the `save_restore_tty()` function used to save and restore terminal settings and file descriptor flags. - Another function, `modify_termios()`, is highlighted for changing terminal settings using specific structures for representation. **Object Detection and Classification:** - The primary object detected is text along with a code block related to a terminal in UNIX systems. **Scene and Activity Analysis:** - The scene depicts an instructional guide presenting theoretical and practical aspects of writing a UNIX terminal test program. - The main activity involves defining and documenting code to save and restore terminal attributes and modifying terminal settings. **Diagram and Chart Analysis:** - There are no diagrams or charts in this image for analysis. **Product Analysis:** - There are no products depicted in this image for analysis. **Anomaly Detection:** - No anomalies are detected. The image appears to be a standard page from a textbook or lecture notes. **Color Analysis:** - The color composition is primarily black text on a white background, typical for printed instructional material. This color scheme emphasizes readability and clarity. **Perspective and Composition:** - The perspective is that of a straight-on view of a printed or digital document. - The composition includes a header, title, body text, and a code snippet organized in a single-column format, typical for academic or instructional material. **Contextual Significance:** - The excerpt contributes to a deeper understanding of programming interactive UNIX terminals, serving as an educational tool for students or professionals learning about terminal I/O control. **Graph and Trend Analysis:** - No graphs or trends are presented in this image for analysis. **Tables:** - There are no tables present in the image. **Ablaufprozesse (Process Flows):** - The process described involves saving and restoring terminal settings and modifying terminal attributes using defined structures. **Prozessbeschreibungen (Process Descriptions):** - Detailed descriptions are provided for the `save_restore_tty()` and `modify_termios()` functions, including the rationale behind their usage, and code implementations for each aspect. **Typen Bezeichnung (Type Designations):** - The text defines types such as `struct tty_opts_tag` for specifying terminal setting options. ### Conclusion The provided image is an excerpt from a chapter of "UNIX Lecture Notes," which focuses on creating a test program for altering and restoring terminal settings. It serves as a detailed guide on implementing terminal I/O control in UNIX, complete with code examples and extensive commentary. The document is structured in a typical academic format, ensuring clarity and ease of understanding for the reader. #################### File: UNIX%20Application%20and%20System%20Programming%2C%20lecture%20notes%20-%20Stewart%20Weiss%20%28PDF%29%20chapter_05.pdf Page: 24 Context: ``` } else { printf("\nInvalid input: %c\n", input); continue; } } time(&time_now); printf("\nTimeout waiting for input: %d secs elapsed," "%d timeouts left\n", (int)(time_now - time0), uip.maxtries); if (uip.maxtries == 0) { printf("\nTime is up.\n"); return 0; } } } ## Comments - The `fflush()` call flushes the buffers associated with the file stream passed to it. The C Standard I/O Library provides buffered I/O for file streams. When a program is started, by default, the streams `stdin`, `stdout`, and `stderr` are line buffered. This means that the characters are transmitted to the terminal only when a newline is placed on the stream. Since functions such as `printf()`, `puts()`, and the others that act on `stdout`, act on file streams, they are line buffered. The preceding `printf()` call ```c printf("%s (y/n)?", uip.prompt); ``` sends a string to `stdout` without a terminated newline and therefore this string will not appear immediately. To force the characters to be delivered to the terminal device, we use `fflush(stdout)`, which empties the buffer. If we comment out the `fflush()` call, the prompt will not appear on the screen until after a `read()` runs. Note that the buffering provided for streams is independent of the buffering done by the terminal within the line discipline. Even if you put the terminal into non-canonical mode, if you use the higher-level C library functions, C will continue to line buffer. You must use the lower-level file descriptor operations to avoid the buffering. - The call to flush the terminal's input queue, `fflush()`, is needed in case the program is run in canonical mode and input is buffered. In this case the user has to enter a newline before the terminal will deliver the characters to the `read()` call, and `get_response()` needs to remove that newline character, otherwise it will be used as the next input character when it is called again. - `get_response()` calls `sleep()` to block itself for the number of seconds given by `uip.sleeptime`. The `sleep()` function's prototype is: ```c unsigned int sleep(unsigned int seconds); ``` This work is copyrighted by Stewart Weiss and licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. ``` Image Analysis: ### Analysis Results #### 1. Localization and Attribution: - **Image Number:** Image 1 - **Location on the Page:** The image occupies the entire visible area of the provided content and contains text and code snippets. #### 2. Object Detection and Classification: - **Detected Objects:** - Text - Code block - **Classification:** - Text: "Comments" section with bullet points and an explanation. - Code block: Contains a C program segment. #### 3. Scene and Activity Analysis: - **Scene Description:** - The image presents an excerpt from an educational document dedicated to UNIX and C programming. - **Activities:** - The document seems to be explaining the concept of input and output buffering in C programming, particularly focusing on the `fflush()` function and related concepts. #### 4. Text Analysis: - **Detected Text:** - Major headings: "UNIX Lecture Notes", "Chapter 5 Interactive Programs and Signals". - Subheading: "Comments". - Body text: Explanation of the `fflush()` function, its purpose, and use in C programming. - **Content Analysis:** - The text explains how the `fflush()` function is used to flush the buffers associated with a file stream. - It covers the role of standard I/O Library in buffered I/O for file streams. - It highlights the significance of ensuring that characters are transmitted immediately to the terminal using `fflush()`. - It also explains the concept of canonical mode and buffered input in the context of terminal communications. - It mentions other important function calls, e.g., `get_response()` and `sleep()`. #### 5. Diagram and Chart Analysis: - **Analysis:** - No diagrams or charts are present in this image. #### 6. Product Analysis: - **Analysis:** - There are no products depicted in this image. #### 7. Anomaly Detection: - **Analysis:** - There are no detectable anomalies in this image. #### 8. Color Analysis: - **Analysis:** - The image is in grayscale with black text over a white background, typical for document scans or screenshots. #### 9. Perspective and Composition: - **Perspective:** - The image is a direct scan or screenshot from a document, presenting a flat, straightforward view of the content. - **Composition:** - The document layout is typical of a textbook or technical manual, with clear sectioning, headings, code blocks, and comments for explanation. #### 10. Contextual Significance: - **Analysis:** - This image is part of a lecture note on UNIX and C programming. - It contributes to the educational content by explaining important programming concepts and functions, aiding students in understanding buffered I/O and terminal input/output handling. #### 11. Metadata Analysis: - **Analysis:** - No metadata is extractable from the provided image. #### 12. Graph and Trend Analysis: - **Analysis:** - No graphs are present in this image. #### 13. Graph Numbers: - **Analysis:** - No data points or graphs are present to analyze. #################### File: UNIX%20Application%20and%20System%20Programming%2C%20lecture%20notes%20-%20Stewart%20Weiss%20%28PDF%29%20chapter_05.pdf Page: 31 Context: # UNIX Lecture Notes **Prof. Stewart Weiss** ## Chapter 5: Interactive Programs and Signals SIGSTOP causes the program to stop by default, and SIGINT causes the process to terminate. The last column indicates the cause or condition that leads to this signal. ### 5.3.4 Sending Signals In UNIX, the kernel can send a signal to a process when some hardware error condition arises. For example, if a program attempts to execute an illegal instruction, the kernel will receive the hardware notification and will send the SIGILL (illegal instruction signal) to the offending process. A process can also send a signal to one or more processes (or even itself) by using the `kill()` system call. The form of the call is: ```c int kill(int processid, int signal); ``` The first parameter stores a means to specify the process id of the process to receive the signal. The second parameter is the kind of signal to send. In the simplest case: ```c kill(942, SIGTERM); ``` sends the `SIGTERM` signal to the process whose process-id is 942. A process cannot send a signal to another process if they do not share the same real or effective user-id. If a process does not have permission to issue the kill call, `kill()` returns -1. `processid` can be 0, -1, or a negative number, and it means something different in each case. If `processid` is 0, the signal will be sent to all processes in the same process group, whereas if it is -1, and the sender is not the superuser, it is sent to all processes for which it has permission to send signals, which are those processes with the same real or effective user-id. If `processid` is less than -1, it is sent to all processes in the process group with id `-processid`. A process can also send a signal to itself using: ```c int raise(int signal); ``` which is equivalent to: ```c kill(getpid(), signal); ``` The call to `raise()` will return only when the process has handled the signal. ### 5.3.5 Signal Generation and Delivery UNIX systems generally distinguish between the generation of a signal and its delivery. According to the Open Group Base Specification Issue 6 (IEEE Std 1003.1), This work is copyrighted by Stewart Weiss and licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. Image Analysis: ### Comprehensive Examination of the Attached Visual Content #### 1. Localization and Attribution: - **Image 1**: There is only one image depicted on the page. #### 4. Text Analysis: - **Detected Text**: - `UNIX Lecture Notes` - `Chapter 5 Interactive Programs and Signals` - `Prof. Stewart Weiss` - `SIGSTOP causes the program to stop by default, and SIGINT causes the process to terminate. The last column indicates the cause or condition that leads to this signal.` - `5.3.4 Sending Signals` - `In UNIX, the kernel can send a signal to a process when some hardware error condition arises. For example, if a program attempts to execute an illegal instruction, the kernel will receive the hardware notification and will send the SIGILL (illegal instruction signal) to the offending process. A process can also send a signal to one or more processes (or even itself) by using the kill() system call. The form of the call is` - `int kill(int processid, int signal);` - `The first parameter stores a means to specify the process id of the process to receive the signal. The second parameter is the kind of signal to send. In the simplest case,` - `kill(942, SIGTERM);` - `sends the SIGTERM signal to the process whose process-id is 942. A process cannot send a signal to another process if they do not share the same real or effective user-id. If a process does not have permission to issue the kill call, kill() returns -1.` - `processid can be 0, -1, or a negative number, and it means something different in each case. If processid is 0, the signal will be sent to all processes in the same process group, whereas if it is -1, and the sender is not the superuser, it is sent to all processes for which it has permission to send signals, which are those processes with the same real or effective user-id. If processid < -1, it is sent to all processes in the process group with id -processid.` - `A process can also send a signal to itself using` - `int raise(int signal);` - `which is equivalent to` - `kill(getpid(), signal); ` - `The call to raise() will return only when the process has handled the signal.` - `5.3.5 Signal Generation and Delivery` - `UNIX systems generally distinguish between the generation of a signal and its delivery. According to the Open Group Base Specification Issue 6 (IEEE Std 1003.1),` - `This work is copyrighted by Stewart Weiss and licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.` - **Content Analysis**: - **Context**: This text is from a UNIX Lecture Note, specifically discussing how signals are sent and delivered in UNIX systems. - **Key Points**: - **Sending Signals**: The process of sending signals in UNIX operating system using the `kill()` system call. - **Code Example 1**: ```c int kill(int processid, int signal); ``` - The two parameters signify the process ID and the type of signal to send. - **Practical Example**: ```c kill(942, SIGTERM); ``` - Sends a termination signal to the process with ID 942. - **Case Descriptions**: - Explains different scenarios determined by the value of `processid` and sender permissions. - **Self-signaling using `raise()`**: ```c int raise(int signal); ``` - Equivalent to sending a signal to the process itself using `kill(getpid(), signal)`. - **Signal Generation and Delivery**: Differentiating between generation and delivery of signals in UNIX systems according to the IEEE Std 1003.1. #### 10. Contextual Significance: - **Overall Message/Theme**: - This page of the lecture notes aims to educate readers on the technical details of UNIX signal handling. - It explains the practical implementation and theoretical understanding necessary for managing signals in UNIX, a crucial concept for system programming and handling processes. #### 8. Color Analysis: - **Color Composition**: The image is largely monochromatic with black text on a white background, typical of text-heavy educational documents. - **Impact on Perception**: The monochromatic color scheme ensures clarity and legibility of the text, facilitating ease of reading and comprehension. #### 9. Perspective and Composition: - **Perspective**: The page is presented from a straight-on perspective, typical for reading material. - **Composition**: The text is organized into clearly defined sections and sub-sections, with headings, code examples, and paragraphs, enhancing readability and structured learning. By focusing on these key aspects, the image provides a detailed and clear explanation of signal handling in UNIX, critical for understanding process management in the operating system. #################### File: BIOS%20Disassembly%20Ninjutsu%20Uncovered%201st%20Edition%20-%20Darmawan%20Salihun%20%28PDF%29%20POST_Memory_Manager_Specification.pdf Page: 1 Context: # POST Memory Manager Specification **Version 1.01** **November 21, 1997** This specification has been made available to the public. You are hereby granted the right to use, implement, reproduce, and distribute this specification with the foregoing rights at no charge. This specification is, and shall remain, the property of Phoenix Technologies Ltd. (“Phoenix”), and Intel Corporation (“Intel”). --- NEITHER PHOENIX NOR INTEL MAKE ANY REPRESENTATION OR WARRANTY REGARDING THIS SPECIFICATION OR ANY PRODUCT OR ITEM DEVELOPED BASED ON THIS SPECIFICATION. USE OF THIS SPECIFICATION FOR ANY PURPOSE IS AT THE RISK OF THE PERSON OR ENTITY USING IT. PHOENIX AND INTEL DISCLAIM ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND FREEDOM FROM INFRINGEMENT. WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, NEITHER PHOENIX NOR INTEL MAKE ANY WARRANTY OF ANY KIND THAT ANY ITEM DEVELOPED BASED ON THIS SPECIFICATION, OR ANY PORTION OF IT, WILL NOT INFRINGE ANY COPYRIGHT, PATENT, TRADE SECRET OR OTHER INTELLECTUAL PROPERTY RIGHT OF ANY PERSON OR ENTITY IN ANY COUNTRY. #################### File: BIOS%20Disassembly%20Ninjutsu%20Uncovered%201st%20Edition%20-%20Darmawan%20Salihun%20%28PDF%29%20POST_Memory_Manager_Specification.pdf Page: 2 Context: # TABLE OF CONTENTS 1. **INTRODUCTION**.............................................................................................3 1.1 **REVISION HISTORY**..................................................................................3 1.1.1 **Technical Editors**...............................................................................3 1.2 **RELATED DOCUMENTS**............................................................................3 1.3 **TERMS**....................................................................................................4 2. **FUNCTIONALITY**............................................................................................5 2.1 **OVERVIEW**..............................................................................................5 2.1.1 **Why a PMM?**...................................................................................5 2.1.2 **PMM Model**....................................................................................5 2.2 **CLIENTS**..................................................................................................5 3. **PMM SERVICES INTERFACE**.........................................................................6 3.1 **DETECTING PMM SERVICES**...................................................................6 3.1.1 **PMM Structure**................................................................................6 3.1.2 **Detection Algorithm**.....................................................................6 3.2 **PMM SERVICES**.....................................................................................6 3.2.1 **Interface Style**..............................................................................7 3.2.2 **Stack Requirements**.....................................................................7 3.2.3 **Memory Block Alignment**................................................................7 3.2.4 **Accessing Extended Memory**........................................................7 3.3 **PMMALLOCATE - FUNCTION 0**...............................................................7 3.3.1 **Description**....................................................................................7 3.3.2 **Function Prototype**........................................................................8 3.3.3 **Parameters**....................................................................................8 3.4 **PMMFREE - FUNCTION 1**......................................................................9 3.4.1 **Description**....................................................................................9 3.4.2 **Function Prototype**........................................................................9 3.4.3 **Parameters**....................................................................................9 3.5 **PMMDEALLOCATE - FUNCTION 2**..........................................................9 3.5.1 **Description**....................................................................................9 3.5.2 **Function Prototype**.......................................................................10 3.5.3 **Parameters**...................................................................................10 3.6 **C LANGUAGE CODING EXAMPLE**..........................................................11 3.7 **ASSEMBLY LANGUAGE CODING EXAMPLE**........................................11 4. **CONVENTIONS FOR CREATING MEMORY BLOCK HANDLES**......................14 4.1 **NAME SELECTION**.................................................................................14 4.1.1 **ISA Product Identifiers**.................................................................14 4.1.2 **Convention for Selecting Handle Values**....................................14 4.2 **RECOMMENDED METHOD FOR THE USE OF NAMED BLOCKS**...........15 4.3 **FINDING OTHER CARDS IN THE SYSTEM**...........................................16 #################### File: BIOS%20Disassembly%20Ninjutsu%20Uncovered%201st%20Edition%20-%20Darmawan%20Salihun%20%28PDF%29%20POST_Memory_Manager_Specification.pdf Page: 3 Context: # 1 Introduction ## 1.1 Revision History | Revision | Date | Changes | |----------|--------------------|---------------------------------------------------------------------------------------------| | 1.01 | November 21, 1997 | Included guidelines on using extended memory during POST. | | | | Clarified the processor mode and the state of Gate A20 during POST. | | | | Definitions for the terms: Big Real Mode, Extended Memory, and Gate A20 were added. | | | | Changed to not clear the contents of memory blocks when they are deallocated. | | | | Simplified the assembly language coding example by using 32-bit instructions and operands. | | | | Clarified the 'C' language code example by adding a function to find the PMM structure. | | 1.0 | September 20, 1996 | Approved for public release. | ## 1.1.1 Technical Editors **Scott Townsend** Phoenix Technologies Ltd. 135 Technology Drive Irvine, CA 92618 Phone: (714) 790-2125 Fax: (714) 790-2001 Email: [Scott.Townsend@Phoenix.com](mailto:Scott.Townsend@Phoenix.com) **Bob Hale** Intel Corporation 5200 N.E. Elam Young Parkway Hillsboro, OR 97124-6497 Phone: (503) 696-4249 Fax: (503) 648-6705 Email: [robert_p_hale@ccm2.hf.intel.com](mailto:robert_p_hale@ccm2.hf.intel.com) ## 1.2 Related Documents | Title | Author | Version | |------------------------------------|------------------------------|---------| | BIOS Boot Specification | Phoenix, Intel, Compaq | 1.01 | | Plug and Play BIOS Specification | Compaq, Phoenix, Intel | 1.0A | | EISA Specification | BCPR Services, Inc. | 3.12 | #################### File: BIOS%20Disassembly%20Ninjutsu%20Uncovered%201st%20Edition%20-%20Darmawan%20Salihun%20%28PDF%29%20POST_Memory_Manager_Specification.pdf Page: 4 Context: # 1.3 Terms ## Big Real Mode **Big Real Mode** is a modified version of the processor’s real mode with the segment limits changed from 1MB to 4GB. Big real mode allows the BIOS or an Option ROM to read and write extended memory without the overhead of protected mode. The BIOS puts the processor in big real mode during POST to allow simplified access to extended memory. The processor will be in big real mode while the PMM services are callable. ## BIOS The **Basic Input Output System** is the system software embedded on a chip located on the computer’s main board. The BIOS executes POST to test and initialize the system components and then boots the operating system. The BIOS also handles the low-level input/output to the various peripheral devices connected to the computer at runtime. Additionally, most BIOSes have a Setup program that allows the user to configure the system. ## Extended Memory The **Extended Memory** area starts at memory address 1MB and ends at memory address 4GB. Extended memory is normally only accessible when the processor is in protected mode. One exception to this is big real mode (see above). Section 3.2.4 provides guidelines as to how a PMM client may access extended memory. ## Gate A20 **Gate A20** controls 1MB memory wrap-around. When Gate A20 is enabled, it forces memory accesses to wrap around and fall within the 0-1MB area by forcing address line 20 to be zero. This has the effect of not allowing access to extended memory. When Gate A20 is disabled, memory accesses beyond 1MB do not wrap around, thus allowing access to all of extended memory. ## Option ROM An **Option ROM** (Read Only Memory) is a software component located in a ROM chip on an add-in card or the system board. Its physical address is in system memory between addresses C0000H and DFFFFH. The BIOS may copy the component to shadow memory during POST. An Option ROM is characterized by the first two locations containing a two-byte signature of 55h AAh. Option ROMs are responsible for initializing their associated hardware, allowing it to be available to the rest of the system for booting or runtime. ## Paragraph A **Paragraph** is 16 contiguous bytes of memory. Paragraph alignment of data means that the address of the data is of the form xxxx0h. ## PMM The **POST Memory Manager** is a software component of the BIOS that provides for the allocation of memory blocks during system POST. ## POST The **Power-On Self-Test** is the part of the BIOS that takes control immediately after the computer is turned on. POST initializes the computer hardware in preparation for loading the operating system. ## Run-Time Execution of run-time software takes place after the operating system has loaded. BIOS run-time services are available at POST and remain callable after the operating system has booted. Application programs and operating systems call BIOS run-time services for hardware-related functions. The PMM services are not callable during run-time, and buffers allocated by the PMM during POST are not available at runtime. #################### File: BIOS%20Disassembly%20Ninjutsu%20Uncovered%201st%20Edition%20-%20Darmawan%20Salihun%20%28PDF%29%20POST_Memory_Manager_Specification.pdf Page: 8 Context: # 3.3.2 Function Prototype ```c unsigned long {entryPoint}( unsigned int function, // 0 for pmAllocate unsigned long length, // in paragraphs unsigned long handle, // handle to assign to memory block unsigned int flags // bit flags specifying options ); ``` ## 3.3.3 Parameters ### function Value for pmAllocate. Invalid values for the function parameter (0x0003…0xFFFF) cause an error value of 0xFFFFFFFF to be returned, signaling that the function is not supported. ### length The size of the requested memory block in paragraphs, or if length is 0x00000000, no memory is allocated and the value returned is the size of the largest memory block available for the memory type specified in the flags parameter. The alignment bit in the flags register is ignored when calculating the largest memory block available. ### handle A client-specified identifier to be associated with the allocated memory block. A handle of 0xFFFFFFFF indicates that no identifier should be associated with the block. Such a memory block is known as an “anonymous” memory block and cannot be found using the pmnFind function (see below). If a specified handle for a requested memory block is already used in a currently allocated memory block, the error value of 0x00000000 is returned. ### flags A bitmap used by the client to designate options regarding memory allocation. | Bits | Field | Value | Description | |-------|--------------|-------|-------------------------------------------------------| | 1.0 | MemoryType | 1.3 | 0 = Invalid | | | | | 1 = Requesting conventional memory block (0 to 1MB). | | | | | 2 = Requesting extended memory block (1MB to 4GB). | | | | | 3 = Requesting either a conventional or an extended memory block, whichever is available. | | 2 | Alignment | 0.1 | 0 = No alignment. | | | | | 1 = Use alignment from the length parameter. | | 15.3 | Reserved | 0 | Reserved for future expansion, must all be zero. | ### flags.MemoryType Specifies whether the requested memory block should be allocated from conventional memory, extended memory, or from either conventional or extended memory. At least one of the bits in this field must be set. If bit 0 is set, the PMM will attempt to allocate only from conventional memory. If bit 1 is set, the PMM will attempt to allocate only from extended memory. If both bits 0 and 1 are set, the PMM will allocate from either type. #################### File: BIOS%20Disassembly%20Ninjutsu%20Uncovered%201st%20Edition%20-%20Darmawan%20Salihun%20%28PDF%29%20POST_Memory_Manager_Specification.pdf Page: 13 Context: ```markdown # 3.7 Assembly Language Coding Example The following assembly language coding example performs the equivalent of the C language example above. Note the use of x86 instructions (pushd, etc.) and 32-bit instruction operands. ```assembly ; Find the PM Services entry point and checksum the structure. call findPMEntry ; DS:SI will point to PM structure. ; Allocate a 16KB buffer and assign our own handle to it. push 0031h ; Specify conventional memory. push 12345678h ; Our handle is 12345678h. push 00000400h ; Buffer size is 16K (40th paragraph). push 0000h ; Specify allocate - function 0. call DWORD PTR [esi + 77] ; Call the entry point in the structure. add sp, 12 ; Clean up stack after call - C style. cmp dx, 0000h ; Buffer address is in DX:AX (32-bit). jbe allocSuccess jmp failed ; Return value of 00000000h is an error. allocSuccess: ; Save our buffer address from DX:AX into EDI. mov di, dx ; Put the upper word into DI. shl di, 16 ; Shift it to upper EDI. mov di, ax ; Put the lower word into EDI. ; Look up the buffer address based on our known handle. push 12345678h ; Our handle is 12345678h. push 0031h ; Specify find - function 1. call DWORD PTR [esi + 77] ; Call the entry point in the structure. add sp, 12 ; Clean up stack after call - C style. cmp dx, 0000h ; Buffer address is in DX:AX (32-bit). jbe findSuccess jmp findFailed ; Return value is in DX:AX (32-bit). findSuccess: push edi ; Retrieve buffer address from EDI. push 002h ; Specify deallocate - function 2. call DWORD PTR [esi + 77] ; Call the entry point in the structure. add sp, 12 ; Clean up stack after call - C style. cmp dx, 0000h ; Return value is in DX:AX (32-bit). jbe passed jmp failed ; Return value of 00000000h is an error. passed: ; No error occurred. ``` ``` #################### File: BIOS%20Disassembly%20Ninjutsu%20Uncovered%201st%20Edition%20-%20Darmawan%20Salihun%20%28PDF%29%20POST_Memory_Manager_Specification.pdf Page: 16 Context: # Support of Multiple Structures With One Named Block ### XYZ0000 ``` Dir | Buffer | |--- BootStruct | |--- BootStruct ``` ### Key - **Anonymous Block** - **Named Block** - **Null Pointer** ## 4.3 Finding Other Cards in the System The use of PnP IDs for named handles has another consequence: it makes it possible to perform a simplified search for other similar cards in the system. Assume that XYZ's Option ROMs always attempt to allocate a block of memory named “XYZ0000”. If two of XYZ's Option ROMs exist in the same system, the second request to allocate will fail. If the company's Option ROMs instead do a `pmmFind` for the handle XYZ0000 prior to attempting to allocate memory with the same handle, the Option ROM can use the previously initialized allocation. In companies with more complex product lines, each set of products may need to use a different “family” ID (e.g., XYZ0000 for one family, XYZ0100 for another, etc.). Pseudocode implementing multiple card support is shown below. ```c #define NoId 0xFFFFFFFF #define XYZ0000 ((*(Y*++)+1) << 26) | \ ((*(Y*++)+1) << 21) | \ ((*(Y*++)+1) << 16) struct dir { struct dir *nextcard; // point to next directory byte *buffer; struct BootStruct *boot; int cardsCS; } dir; struct dir *base, *t; // pmmAllocate is assumed to be defined as above. if ((base = (*entryPoint)(PMM_FIND, XYZ0000)) != 0) { t = pmmAllocate(NoId, (sizeof(dir) + 15) / 16); t->nextcard = base->nextcard; base = t; } ``` #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20%20UsingOberon.pdf Page: 2 Context: # System Commands | Command | Description | |----------------|--------------------------------------| | System.Close | close the viewer | | Edit.Store | store the text as a file | | Edit.Search | search for the selected word from the position of the caret | ## Editing Texts The most frequent task is editing a text. For this case, some commands can be issued by simple mouse clicks alone rather than clicking the command name. When a text is to be entered, it is always inserted at the position of the caret displayed as a hook. The caret is positioned by pointing (with the cursor) at the desired position and clicking the left button (pointer button). Then the text is entered by simply typing it. A piece of text can be selected in order to be subjected to a subsequent command. This is done by moving the cursor over the piece of text while holding the right button (select button) pressed. Often it is only necessary to select the first character of a parameter. Selection can be turned into deletion by briefly clicking also the left button while holding the right button pressed. This is called inter-clicking. Similarly, a piece of text being selected can be copied over to the caret position by inter-clicking the middle button. The functions of the mouse buttons are summarized by the following table: | Inter-click | left | middle | right | |----------------|---------------------|---------------|------------------| | Primary click: | set caret | - | copy | | | command | - | - | | | select | delete | copy | The keyboard features two special keys, so-called control keys. The `Esc` key undoes selections. The `Backspace` key deletes the character left of the caret. Text viewers have a scroll bar at their left edge. While the cursor is in the scroll bar, it assumes the form of an up/down pointer to show its difference in functionality. Clicking a button then causes the text to scroll up or down. - **Left button:** the current line moves up to the top of the viewer - **Middle button:** shows the section at the relative position given by the cursor - **Right button:** the top line moves down to the current cursor position ## Viewer Handling Viewers can be extended, moved, or copied. A viewer is enlarged or shrunk by clicking the left button, while the cursor is in the title bar, and then dragging the bar up or down. A viewer is moved to another location by also inter-clicking with the middle button. A duplicate of a viewer may be generated by activating the command `System.Copy` in the title bar. Note that in this case the old and the new viewer show the same text, and not a copy of the text. This facility comes in handy when a piece of text needs to be #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20%20UsingOberon.pdf Page: 3 Context: # System Tool Commands The command `System.grow` in the title bar generates a copy extending over the entire column (or over the entire display). By closing the viewer (command `System.close` in the title bar), the original viewer reappears. We may imagine that `grow` lifts a viewer to an overlay in the third dimension. ## Commands The following commands appear in the standard tool `System.Tool`. The character `^` indicates that a name must be selected previously. The command then applies to that named text (file, as in the example above). The character `~` indicates that a list of names must be inserted before the `~` character, and the command will apply to all named objects. | Command | Description | |-------------------------|---------------------------------------------------------| | `System.Open ^` | open viewer in the system track to the right | | `System.Recall` | close the last viewer opened | | `Edit.Open ^` | open viewer in the user track to the left | | `Edit.Recall` | undo last editing operation | | `Edit.ChangeFont` | applies to selected piece of text | | `Edit.SetFont` | use specified font for subsequent input | | `System.Directory ^` | search directory for specified file names | | `System.Free ~` | remove specified modules from store | | `System.CopyFiles ->` | e.g. `file1 => file2 file3 => file4` | | `System.RenameFiles ->` | e.g. `file1 => file2 file3 => file4` | | `System.DeleteFiles ->` | e.g. `file1 file2 file3 ->` (from file directory) | | `System.ShowModules` | | | `System.ShowCommands ^`| compile selected text | | `Hilbert.Draw` | draw Hilbert curve, as an example | When clicking a command `M.P.`, module `M` is searched in the file store and, if found and not already present, loaded into main store. Then its command `P` is searched and executed (if found). A list of loaded modules can be generated by the command `System.ShowModules`, and a list of its commands is obtained by the command `System.ShowCommands`. Any parameter-less procedure in any (compiled) module is accessible as a command. Its parameters are accessed via a scanner. As an example, consider the following short program: ```pascal MODULE M0: IMPORT Texts, Oberon; VAR W: Texts.Writer; PROCEDURE P0; VAR sum: INTEGER; S: Texts.Scanner; BEGIN sum := 0; Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S); WHILE S.Class = Texts.Int DO Texts.Writeln(W, S.i, ':'); sum := sum + S.i; Texts.Scan(S); END; END; ``` #################### File: Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20%20UsingOberon.pdf Page: 4 Context: ``` Texts.Write(W, sum, 8); Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf) END P0; BEGIN Texts.OpenWriter(W) END M0. After its successful compilation (ORP.Compile @), the command M0.PO 2 3 5 7 11 causes these numbers and their sum to be output to the standard viewer **System.Log**. ## The core of the Oberon System The system's core consists of a loop which continuously senses for a command to appear. The command is identified, control is dispatched, and the command is executed. A command may stem from an explicit click (middle button) on a text of the form M.P, or it may be a click of the left or right mouse buttons (see editing commands). A further source of input is the keyboard. If any key is pressed, this is interpreted as a command to read that character. Exceptions are the **esc**, **ctrl-z** (or **F1**), and **backspace** keys. **esc** is interpreted as a command to undo all selections, **backspace** to remove the character left of the caret and **ctrl-z** to set the global marker. ``` yes no mouse key? | keyboard? ``` The initially loaded system contains, apart from module Oberon, the command module **System**, a text system (modules TextFrames, MenuViewers, Texts, Fonts, Input), a viewer system (modules Viewers, Display), the loader and linker (module Modules), a file system (modules Files, FileDir), and the disk space manager and the garbage collector (module Kernel). The compiler is loaded on demand, like other application programs. [Project Oberon - ETH Zurich](https://www.inf.ethz.ch/personal/wirth/ProjectOberon/index.html) [Project Oberon](http://www.projectoberon.com/) ``` ########## """QUERY: tell me more about the git version control""" Consider the chat history for relevant information. Use all information included. Use as much tokens as needed. Important: If you find information separated by a | in the context, it is a table formatted in Markdown.Important: Take a look at the QUERY and only the QUERY. If this is vague or unclear, please ignore everything and ask a follow-up question instead! Final Files Sources: Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 1, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 2, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 3, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 4, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 5, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 6, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 7, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 8, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 9, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 10, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 11, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 12, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 13, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 14, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 15, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 16, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 17, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 18, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 19, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 20, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 21, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 22, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 23, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 24, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 25, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 26, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 27, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 28, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 29, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 30, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 31, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 32, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 33, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 34, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 35, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 36, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 37, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 38, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 39, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 40, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 41, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 42, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 43, Git%20Magic%20-%20Ben%20Lynn%2C%20et%20al.%20%28HTML%2C%20PDF%2C%20EPUB%29.pdf - Page 44, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 1, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 2, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 4, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 6, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 8, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 12, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 13, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 15, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 17, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 19, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 28, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 33, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 35, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 39, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 44, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 45, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 47, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 48, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 49, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 50, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 51, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 52, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 53, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 54, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 55, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 58, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 60, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 61, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 64, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 66, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 71, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 73, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 74, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 76, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 79, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 80, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 81, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 83, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 85, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20PO.Applications.pdf - Page 86, UNIX%20Application%20and%20System%20Programming%2C%20lecture%20notes%20-%20Stewart%20Weiss%20%28PDF%29%20chapter_05.pdf - Page 3, UNIX%20Application%20and%20System%20Programming%2C%20lecture%20notes%20-%20Stewart%20Weiss%20%28PDF%29%20chapter_05.pdf - Page 4, UNIX%20Application%20and%20System%20Programming%2C%20lecture%20notes%20-%20Stewart%20Weiss%20%28PDF%29%20chapter_05.pdf - Page 12, UNIX%20Application%20and%20System%20Programming%2C%20lecture%20notes%20-%20Stewart%20Weiss%20%28PDF%29%20chapter_05.pdf - Page 22, UNIX%20Application%20and%20System%20Programming%2C%20lecture%20notes%20-%20Stewart%20Weiss%20%28PDF%29%20chapter_05.pdf - Page 24, UNIX%20Application%20and%20System%20Programming%2C%20lecture%20notes%20-%20Stewart%20Weiss%20%28PDF%29%20chapter_05.pdf - Page 31, BIOS%20Disassembly%20Ninjutsu%20Uncovered%201st%20Edition%20-%20Darmawan%20Salihun%20%28PDF%29%20POST_Memory_Manager_Specification.pdf - Page 1, BIOS%20Disassembly%20Ninjutsu%20Uncovered%201st%20Edition%20-%20Darmawan%20Salihun%20%28PDF%29%20POST_Memory_Manager_Specification.pdf - Page 2, BIOS%20Disassembly%20Ninjutsu%20Uncovered%201st%20Edition%20-%20Darmawan%20Salihun%20%28PDF%29%20POST_Memory_Manager_Specification.pdf - Page 3, BIOS%20Disassembly%20Ninjutsu%20Uncovered%201st%20Edition%20-%20Darmawan%20Salihun%20%28PDF%29%20POST_Memory_Manager_Specification.pdf - Page 4, BIOS%20Disassembly%20Ninjutsu%20Uncovered%201st%20Edition%20-%20Darmawan%20Salihun%20%28PDF%29%20POST_Memory_Manager_Specification.pdf - Page 8, BIOS%20Disassembly%20Ninjutsu%20Uncovered%201st%20Edition%20-%20Darmawan%20Salihun%20%28PDF%29%20POST_Memory_Manager_Specification.pdf - Page 13, BIOS%20Disassembly%20Ninjutsu%20Uncovered%201st%20Edition%20-%20Darmawan%20Salihun%20%28PDF%29%20POST_Memory_Manager_Specification.pdf - Page 16, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20%20UsingOberon.pdf - Page 2, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20%20UsingOberon.pdf - Page 3, Project%20Oberon%20The%20Design%20of%20an%20Operating%20System%2C%20a%20Compiler%2C%20and%20a%20Computer%20-%20Niklaus%20Wirth%2C%20J%C3%BCrg%20Gutknecht%20%28PDF%29%20%20UsingOberon.pdf - Page 4 ================================================== **Elapsed Time: 0.00 seconds** ================================================== GEMINI ERROR -- FALLBACK TO GPT MESSAGE: The model response did not completed successfully. Finish reason: 3. Finish message: . Safety ratings: [category: HARM_CATEGORY_HATE_SPEECH probability: NEGLIGIBLE probability_score: 0.1953125 severity: HARM_SEVERITY_MEDIUM severity_score: 0.482421875 , category: HARM_CATEGORY_DANGEROUS_CONTENT probability: MEDIUM probability_score: 0.6953125 severity: HARM_SEVERITY_MEDIUM severity_score: 0.6328125 blocked: true , category: HARM_CATEGORY_HARASSMENT probability: NEGLIGIBLE probability_score: 0.0717773438 severity: HARM_SEVERITY_NEGLIGIBLE severity_score: 0.153320312 , category: HARM_CATEGORY_SEXUALLY_EXPLICIT probability: NEGLIGIBLE probability_score: 0.056640625 severity: HARM_SEVERITY_NEGLIGIBLE severity_score: 0.17578125 ]. To protect the integrity of the chat session, the request and response were not added to chat history. To skip the response validation, specify `model.start_chat(response_validation=False)`. Note that letting blocked or otherwise incomplete responses into chat history might lead to future interactions being blocked by the service.================================================== FINAL ANSWER Answer: Git is a powerful and flexible version control system widely used for tracking changes in source code during software development. It allows multiple developers to work on a project simultaneously without overwriting each other's changes. Here is a detailed overview of Git version control based on the provided context: ### Overview of Git Git is often described as a "version control Swiss army knife" due to its versatility and reliability. It is a distributed version control system, meaning that every user has a complete copy of the repository, including its full history. This design allows for robust collaboration and ensures that the repository can be recovered from any user's local copy if needed. ### Key Concepts and Features #### 1. **Version Control Paradigms** Git supports both centralized and distributed version control paradigms. In a centralized system, a single server holds the repository, and users check out and commit changes to this central repository. In contrast, Git's distributed nature means that each user has a full copy of the repository, allowing for operations like commits, branching, and merging to be performed locally. #### 2. **Basic Operations** - **Initialization**: A new Git repository is created using `git init`. - **Adding Files**: Files are added to the staging area using `git add`. - **Committing Changes**: Changes are committed to the repository with `git commit`. - **Cloning Repositories**: A repository can be cloned using `git clone`, which creates a local copy of the repository. - **Pulling Changes**: Updates from a remote repository are fetched and merged using `git pull`. - **Pushing Changes**: Local commits are sent to a remote repository using `git push`. #### 3. **Branching and Merging** Git's branching model is one of its most powerful features. Branches allow developers to work on different features or fixes independently. Merging integrates changes from different branches. Git handles simple merges automatically but requires manual intervention for conflicts. #### 4. **Distributed Nature** In Git, every clone of the repository is a full-fledged repository with complete history. This design allows for offline work and reduces dependency on a central server. It also enhances collaboration, as changes can be shared directly between developers. #### 5. **Staging Area** The staging area (or index) is a unique feature of Git. It allows users to prepare changes for the next commit. This intermediate area lets users review and modify changes before they are committed. ### Advanced Features #### 1. **Rebasing** Rebasing is a way to integrate changes from one branch into another. It rewrites the commit history to create a linear sequence of commits. This can make the history cleaner but should be used with caution, especially on shared branches. #### 2. **Cherry-Picking** Cherry-picking allows users to apply specific commits from one branch to another. This is useful for applying bug fixes or features from one branch to another without merging the entire branch. #### 3. **Stashing** Stashing temporarily shelves changes in the working directory that are not ready to be committed. This allows users to switch branches without committing incomplete work. #### 4. **Hooks** Git hooks are scripts that run automatically at certain points in the Git workflow. They can be used for tasks like enforcing commit policies, running tests, or formatting code. ### Example Commands #### Basic Commands ```bash $ git init $ git add . $ git commit -m "Initial commit" $ git clone $ git pull $ git push ``` #### Branching and Merging ```bash $ git branch $ git checkout $ git merge ``` #### Rebasing ```bash $ git rebase ``` #### Stashing ```bash $ git stash $ git stash apply ``` ### Example Workflows #### Feature Branch Workflow 1. **Create a new branch for the feature**: ```bash $ git checkout -b feature-branch ``` 2. **Work on the feature and commit changes**: ```bash $ git add . $ git commit -m "Work on feature" ``` 3. **Merge the feature branch into the main branch**: ```bash $ git checkout main $ git merge feature-branch ``` #### Hotfix Workflow 1. **Create a hotfix branch from the main branch**: ```bash $ git checkout -b hotfix-branch main ``` 2. **Apply the hotfix and commit changes**: ```bash $ git add . $ git commit -m "Apply hotfix" ``` 3. **Merge the hotfix branch back into the main branch**: ```bash $ git checkout main $ git merge hotfix-branch ``` ### Conclusion Git is a robust and flexible version control system that supports a wide range of workflows and collaboration models. Its distributed nature, powerful branching and merging capabilities, and extensive set of features make it an essential tool for modern software development. Whether you are working on a small project or a large-scale enterprise application, Git provides the tools needed to manage your code effectively. ================================================== **Elapsed Time: 25.67 seconds** ==================================================